久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3215|回復: 12
收起左側

STC15W408AS單片機系列通過I/O設置PWM輸出(不是使用PWM功能)程序有沒有第二種思路?

[復制鏈接]
ID:1029559 發表于 2022-5-25 17:57 | 顯示全部樓層 |閱讀模式
單片機芯片使用STC15W408AS,由于PWM端數量只有3路,但實際使用到需要4路,為方便使用編寫一段PWM,占空比是1/3,向大家分享下。

想了很久,自己思維定式,向大家請教,有沒有另外一種更簡潔的方案,并且能使PWM占空比是1:4(開:關),占空比的波形盡量小,謝謝大家,我繼續思考中

單片機源程序如下,給大家分享看
u16 xdata JS1=0;  //計時時間
u16 xdata JS2=0;  //計時時間
u16 xdata JS3=0;  //計時時間
u16 xdata JS4=0;  //計時時間
u16 xdata JS11=0;  //計時時間
u16 xdata JS22=0;  //計時時間
u16 xdata JS33=0;  //計時時間
u16 xdata JS44=0;  //計時時間
u16 xdata JS111=0;  //計時時間
u16 xdata JS222=0;  //計時時間
u16 xdata JS333=0;  //計時時間
u16 xdata JS444=0;  //計時時間
u16 xdata QD1=60;    //啟動閥的時間
u16 xdata QD2=61;    //啟動閥的時間
u16 xdata GB1=20;    //關閉延時
bit bdata IN1_BZ=0;
bit bdata IN2_BZ=0;
bit bdata IN3_BZ=0;
bit bdata IN4_BZ=0;

u16 xdata time_cnt;
bit bdata FZ_BZ=0;

void T0_Init(void)    //T0初始化 60μS 11.0592
{
        AUXR |= 0x80;        //設置為1T工作模式
        TMOD &= 0xF0;        //設置定時器模式
        TL0 = 0x68;        //設置定時初始值
        TH0 = 0xFD;        //設置定時初始值
        TF0 = 0;                //清除TF0
        TR0 = 1;                //定時器0啟動
        ET0=1;      //T0開
        EA=1;        //總中斷開
}
void T0_ZD(void) interrupt 1  //
{  
                time_cnt++;
                if(time_cnt<1000)
                {
                        FZ_BZ=0;
                }
                else if(time_cnt<2000)
                {
                        FZ_BZ=1;
                }
                else
                {
                        time_cnt=0;
                }
    if(FZ_BZ==0) //判斷是否有輸入信號
          {
                  JS111=0;
                  JS1++;
                          IN1_BZ=1;
                        if(JS1<=QD1)        //直接給電
                  {
                          OUT1=0;   //開閥
                  }
                  else                        //進入pwm
                  {
                          JS1=QD2;
                          JS11++;
                          if(JS11<=1)//直接給電
                          {
                                  OUT1=0;   //開閥
                          }
                          else                //不給電
                          {
                                 if(JS11==3)
                                 {
                                         JS11 = 0;        //置0
                                 }
                                 OUT1=1;   //關閥
                          }
                        }
                }  
          else
          {
                        JS111++;
                        if(JS111<GB1)//
                        {
                                OUT1=0;
                        }
                        else
                        {
                                OUT1=1;
                                JS1=0;
                                IN1_BZ=0;
                        }
          }
//***************************************************************************        
if(FZ_BZ==0) //判斷是否有輸入信號
          {
                  JS222=0;
                  JS2++;
                  IN2_BZ=1;
                if(JS2<=QD1)        //直接給電
                  {
                          OUT2=0;   //開閥
                  }
                  else                        //進入pwm
                  {
                          JS2=QD2;
                          JS22++;
                          if(JS22<=1)//直接給電
                          {
                                  OUT2=0;   //開閥
                          }
                          else                //不給電
                          {
                                 if(JS22==3)
                                 {
                                         JS22 = 0;        //置0
                                 }
                                 OUT2=1;   //關閥
                          }
                        }
                }  
          else
          {
                        JS222++;
                        if(JS222<GB1)
                        {
                         OUT2=0;
                        }
                        else
                        {
                                OUT2=1;
                                JS2=0;
                                IN2_BZ=0;
                        }
         }        
//***********************************************************************
if(FZ_BZ==0) //判斷是否有輸入信號
          {   
                  JS333=0;
                  JS3++;
                  IN3_BZ=1;
                if(JS3<=QD1)        //直接給電
                  {
                          OUT3=0;   //開閥
                  }
                  else                        //進入pwm
                  {
                           JS3=QD2;
                          JS33++;
                          if(JS33<=1)//直接給電
                          {
                                  OUT3=0;   //開閥
                          }
                          else                //不給電
                          {
                                 if(JS33==3)
                                 {
                                         JS33 = 0;        //置0
                                 }
                                 OUT3=1;   //關閥
                          }
                        }
                }  
          else
          {
                        JS333++;
                        if(JS333<GB1)
                        {
                         OUT3=0;
                        }
                        else
                        {
                                OUT3=1;
                                JS3=0;
                                IN3_BZ=0;
                        }
         }        
//************************************************************
if(FZ_BZ==0) //判斷是否有輸入信號
          {
                  JS444=0;
                  JS4++;
                  IN4_BZ=1;
                        if(JS4<=QD1)        //直接給電
                  {
                          OUT4=0;   //開閥
                  }
                  else                        //進入pwm
                  {
                           JS4=QD2;
                          JS44++;
                          if(JS44<=1)//直接給電
                          {
                                  OUT4=0;   //開閥
                          }
                          else                //不給電
                          {
                                 if(JS44==3)
                                 {
                                         JS44 = 0;        //置0
                                 }
                                 OUT4=4;   //關閥
                                }
                        }
                }  
          else
          {
                        JS444++;
                        if(JS444<GB1)
                        {
                         OUT4=0;
                        }
                        else
                        {
                                OUT4=1;
                                JS4=0;
                                IN4_BZ=0;
                        }
                }
}


回復

使用道具 舉報

ID:161164 發表于 2022-5-26 00:33 | 顯示全部樓層
用xdata來運算是很耗時的經仿真,你的中斷最少用44us,最多用87us,
已經超過中斷時間了
2022-05-26_002102.png


把所有xdata改回普通data,耗時立刻減少,
但PWM寫法還是有點累贅
2022-05-26_002226.png


用簡潔一點的寫法大大減少中斷耗時
2022-05-26_001815.png


回復

使用道具 舉報

ID:1029559 發表于 2022-5-26 08:40 | 顯示全部樓層
lkc8210 發表于 2022-5-26 00:33
用xdata來運算是很耗時的經仿真,你的中斷最少用44us,最多用87us,
已經超過中斷時間了

感謝指教,確實減少了許多,中斷時間加快了,那后面PWM用while?
回復

使用道具 舉報

ID:339654 發表于 2022-5-26 08:52 | 顯示全部樓層
可以用定時器模擬一路PWM
回復

使用道具 舉報

ID:390416 發表于 2022-5-26 09:35 | 顯示全部樓層
u8 idata PWM_Write_Byte[4]=0;                                // 占空比
#define FOSC 30000000UL                                                // 聲明系統頻率,30M,要與STC-ISP同步設置
#define PWM_F 1000                                                        // 設置PWM頻率,不宜太高。
#define PWM_D 255                                                        // 設置占空閾值,必須大于占空比的最大值,并且小于256
#define PWM_TL (256-(FOSC/12/PWM_F/PWM_D))        // 計算定時器初值(8位)

// 定時器0初始化  
void PWM_Init()
{
        TMOD &= 0xF0;                                  //配置定時器工作模式
        TMOD |= 0x02;                                          //配置定時器工作模式 8位自動重裝模式
    TL0 = PWM_TL;                                    //定時器初值
    TH0 = PWM_TL;                                    //定時器重裝初值
    TR0 = 1;                                        //啟動定時器0
    ET0=1;                                  //允許定時器0申請中斷
    EA=1;                                   //中斷總閘閉合
}

//定時器0的CPU處理函數,位置任意寫都行
void PWM_Display_timer0() interrupt 1
{
        static u8 pwm_t=0;                        //局部變量,不丟失數據
               
                if(pwm_t<PWM_Write_Byte[2])
        {
                        PWM_GPIO_G=0;                                  //綠                       
        }
        else PWM_GPIO_G=1;
        pwm_t++;
                pwm_t=pwm_t%PWM_D;                                        //限制占空比小于占空閾值
}
回復

使用道具 舉報

ID:161164 發表于 2022-5-26 10:47 來自手機 | 顯示全部樓層
xjin1989 發表于 2022-5-26 08:40
感謝指教,確實減少了許多,中斷時間加快了,那后面PWM用while?

什么叫"那后面PWM用while?"
回復

使用道具 舉報

ID:1029559 發表于 2022-5-26 10:57 | 顯示全部樓層
weijoyer 發表于 2022-5-26 08:52
可以用定時器模擬一路PWM

這是個方案,但定時器有其他功能占用了,需要用普通I/O口來模擬PWM信號
回復

使用道具 舉報

ID:1029559 發表于 2022-5-26 11:00 | 顯示全部樓層
lkc8210 發表于 2022-5-26 10:47
什么叫"那后面PWM用while?"

老師,我是看到你最后用了while,你看哈
void main()
{
     T0_Init();
     while(1);
}
你前面是設置開關的時間占比吧,后面就是用while循環反復吧
回復

使用道具 舉報

ID:1029559 發表于 2022-5-26 11:02 | 顯示全部樓層
人人學會單片機 發表于 2022-5-26 09:35
u8 idata PWM_Write_Byte[4]=0;                                // 占空比
#define FOSC 30000000UL                                                // 聲明系統頻率,30M,要與S ...

這是用到的PWM口吧
回復

使用道具 舉報

ID:624769 發表于 2022-5-26 22:00 | 顯示全部樓層
本帖最后由 188610329 于 2022-5-26 22:01 編輯

既然,你只需要4路PWM, 既然你單片機本來就有 3路PWM,  那么你定時器只需要 模擬一路PWM即可,那么完全不用那么頻繁的中斷定時器,直接利用定時器的自動重載功能,可以做到 模擬出MHz級別的 PWM,占用資源還少……。

#include <STC15F2K60S2.H>

//============ 手動設置部分  ===============
#define        Mainforse                33177600L        //晶振頻率(Hz)
#define        Pulse_frequency                420                //脈沖頻率(Hz)        即一秒鐘發生多少個脈沖。
#define        Pulse_High                1                //高電平占比        占空比為(Pulse_High/(Pulse_High + Pulse_Low))
#define        Pulse_Low                4                //低電平占比
sbit        PWMIO = P2^0;
//============ 手動設置部分  ===============

//============        自動設置部分 ===============
#define        Pulse_Count_High        (Mainforse * Pulse_High / Pulse_frequency /(Pulse_High + Pulse_Low))
#define        Pulse_Count_Low                (Mainforse * Pulse_Low / Pulse_frequency /(Pulse_High + Pulse_Low))
#if        ((Pulse_Count_High  < 65536) && (Pulse_Count_Low  < 65536))
        #define        SET_T0_CLK()        AUXR        |= 0x80
        #define        Reload_High        (65536 - Pulse_Count_High)
        #define        Reload_Low        (65536 - Pulse_Count_Low)
#else
        #define        SET_T0_CLK()        AUXR        &= 0x7f
        #define        Reload_High        (65536 - (Pulse_Count_High / 12))
        #define        Reload_Low        (65536 - (Pulse_Count_Low / 12))
#endif
//============        自動設置部分 ===============


void        Main()
{
        SET_T0_CLK();
        TMOD        = 0x00;                        //16位自動重載模式
        TH0        = Reload_High / 256;        //給高電平計數值
        TL0        = Reload_High % 256;
        TR0        = 1;
        PT0        = 1;
        ET0        = 1;
        EA        = 1;
        PWMIO        = 1;                        //IO給高電平
        TH0        = Reload_Low / 256;        //給低電平計數值
        TL0        = Reload_Low % 256;
        while(1);
}

void        T0_INT()        interrupt 1
{
        if(PWMIO)
        {
                PWMIO        = 0;
                TH0        = Reload_High / 256;
                TL0        = Reload_High % 256;
        }
        else
        {
                PWMIO        = 1;
                TH0        = Reload_Low / 256;
                TL0        = Reload_Low % 256;
        }
}

回復

使用道具 舉報

ID:161164 發表于 2022-5-26 22:49 來自手機 | 顯示全部樓層
xjin1989 發表于 2022-5-26 11:00
老師,我是看到你最后用了while,你看哈
void main()
{

老師不敢當,互相交流
那是因為看不懂中斷里的部分代表
就不寫了
直接弄個while(1)
回復

使用道具 舉報

ID:1029559 發表于 2022-5-27 13:26 | 顯示全部樓層
188610329 發表于 2022-5-26 22:00
既然,你只需要4路PWM, 既然你單片機本來就有 3路PWM,  那么你定時器只需要 模擬一路PWM即可,那么完全不用 ...

對哦,我是可以三路PWM的換到其他地方去
回復

使用道具 舉報

ID:1029559 發表于 2022-5-27 13:27 | 顯示全部樓層
人人學會單片機 發表于 2022-5-26 09:35
u8 idata PWM_Write_Byte[4]=0;                                // 占空比
#define FOSC 30000000UL                                                // 聲明系統頻率,30M,要與S ...

打開新的窗口啊
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 中文字幕黄色大片 | www操操 | 天堂色综合 | 国产成人精品一区二区三区在线 | 欧美美女爱爱视频 | 久久免费香蕉视频 | 亚洲国产成人精品久久久国产成人一区 | 一区二区三区中文字幕 | 精品在线一区 | 欧洲尺码日本国产精品 | 日韩视频区 | 欧美久久不卡 | 91视频久久 | 亚洲精品黄色 | 高清国产一区二区 | 久久国产婷婷国产香蕉 | 色小姐综合网 | 欧美性猛交一区二区三区精品 | 中文字幕日韩一区二区 | 久久国产区 | 亚洲欧美在线观看 | 亚洲精品99999 | 一区二区亚洲 | 国产精品乱码一区二区三区 | 日韩在线一区二区三区 | 不卡在线视频 | 精品在线99 | 综合网在线 | 欧美日韩视频 | 美女久久视频 | 日韩成人在线观看 | 久久99久久99精品免视看婷婷 | 久久久久国产一区二区三区四区 | 黄免费观看视频 | 亚洲精品在线免费观看视频 | 欧美lesbianxxxxhd视频社区 | 91亚洲精品在线观看 | 成人av在线播放 | 国产一区精品 | 日韩日韩日韩日韩日韩日韩日韩 | 美女毛片 |