[DemoCode下载] ML51通过PWM实现呼吸灯功能

[复制链接]
1719|10
 楼主| xuanhuanzi 发表于 2023-11-28 20:04 | 显示全部楼层 |阅读模式
ML51_PWM_BreathingLED-main.zip (3.12 MB, 下载次数: 4)
  1. /*_____ I N C L U D E S ____________________________________________________*/
  2. #include "ML51.h"

  3. #include        "project_config.h"



  4. /*_____ D E C L A R A T I O N S ____________________________________________*/
  5. volatile uint8_t u8TH0_Tmp = 0;
  6. volatile uint8_t u8TL0_Tmp = 0;

  7. //UART 0
  8. //bit BIT_TMP;
  9. //bit BIT_UART;
  10. //bit uart0_receive_flag=0;
  11. //unsigned char uart0_receive_data;

  12. /*_____ D E F I N I T I O N S ______________________________________________*/
  13. #define SYS_CLOCK                                                                 (24000000ul)
  14. #define PWM_FREQ                                                                 (10000ul)
  15. #define PWM_RESOLUTION                                (100)
  16. #define PWM_CHANNEL                                   (2)


  17. /*_____ M A C R O S ________________________________________________________*/

  18. volatile uint32_t BitFlag = 0;

  19. uint32_t counter_tick = 0;

  20. /*_____ F U N C T I O N S __________________________________________________*/


  21. void tick_counter(void)
  22. {
  23.         counter_tick++;
  24. }

  25. uint32_t get_tick(void)
  26. {
  27.         return (counter_tick);
  28. }

  29. void set_tick(uint32_t t)
  30. {
  31.         counter_tick = t;
  32. }

  33. void compare_buffer(uint8_t *src, uint8_t *des, int nBytes)
  34. {
  35.     uint16_t i = 0;       
  36.        
  37.     for (i = 0; i < nBytes; i++)
  38.     {
  39.         if (src[i] != des[i])
  40.         {
  41.             printf("error idx : %4d : 0x%2X , 0x%2X\r\n", i , src[i],des[i]);
  42.                         set_flag(flag_error , Enable);
  43.         }
  44.     }

  45.         if (!is_flag_set(flag_error))
  46.         {
  47.             printf("compare_buffer finish \r\n");       
  48.                 set_flag(flag_error , Disable);
  49.         }

  50. }

  51. void reset_buffer(void *dest, unsigned int val, unsigned int size)
  52. {
  53.     uint8_t *pu8Dest;
  54. //    unsigned int i;
  55.    
  56.     pu8Dest = (uint8_t *)dest;

  57.         #if 1
  58.         while (size-- > 0)
  59.                 *pu8Dest++ = val;
  60.         #else
  61.         memset(pu8Dest, val, size * (sizeof(pu8Dest[0]) ));
  62.         #endif
  63.        
  64. }

  65. void copy_buffer(void *dest, void *src, unsigned int size)
  66. {
  67.     uint8_t *pu8Src, *pu8Dest;
  68.     unsigned int i;
  69.    
  70.     pu8Dest = (uint8_t *)dest;
  71.     pu8Src  = (uint8_t *)src;


  72.         #if 0
  73.           while (size--)
  74.             *pu8Dest++ = *pu8Src++;
  75.         #else
  76.     for (i = 0; i < size; i++)
  77.         pu8Dest[i] = pu8Src[i];
  78.         #endif
  79. }

  80. void dump_buffer(uint8_t *pucBuff, int nBytes)
  81. {
  82.     uint16_t i = 0;
  83.    
  84.     printf("dump_buffer : %2d\r\n" , nBytes);   
  85.     for (i = 0 ; i < nBytes ; i++)
  86.     {
  87.         printf("0x%2X," , pucBuff[i]);
  88.         if ((i+1)%8 ==0)
  89.         {
  90.             printf("\r\n");
  91.         }            
  92.     }
  93.     printf("\r\n\r\n");
  94. }

  95. void  dump_buffer_hex(uint8_t *pucBuff, int nBytes)
  96. {
  97.     int     nIdx, i;

  98.     nIdx = 0;
  99.     while (nBytes > 0)
  100.     {
  101.         printf("0x%04X  ", nIdx);
  102.         for (i = 0; i < 16; i++)
  103.             printf("%02X ", pucBuff[nIdx + i]);
  104.         printf("  ");
  105.         for (i = 0; i < 16; i++)
  106.         {
  107.             if ((pucBuff[nIdx + i] >= 0x20) && (pucBuff[nIdx + i] < 127))
  108.                 printf("%c", pucBuff[nIdx + i]);
  109.             else
  110.                 printf(".");
  111.             nBytes--;
  112.         }
  113.         nIdx += 16;
  114.         printf("\n");
  115.     }
  116.     printf("\n");
  117. }

  118. void delay(uint16_t dly)
  119. {
  120. /*
  121.         delay(100) : 14.84 us
  122.         delay(200) : 29.37 us
  123.         delay(300) : 43.97 us
  124.         delay(400) : 58.5 us       
  125.         delay(500) : 73.13 us       
  126.        
  127.         delay(1500) : 0.218 ms (218 us)
  128.         delay(2000) : 0.291 ms (291 us)       
  129. */

  130.         while( dly--);
  131. }


  132. void send_UARTString(uint8_t* Data)
  133. {
  134.         #if 1
  135.         uint16_t i = 0;

  136.         while (Data[i] != '\0')
  137.         {
  138.                 #if 1
  139.                 SBUF = Data[i++];
  140.                 #else
  141.                 UART_Send_Data(UART0,Data[i++]);               
  142.                 #endif
  143.         }

  144.         #endif

  145.         #if 0
  146.         uint16_t i = 0;
  147.        
  148.         for(i = 0;i< (strlen(Data)) ;i++ )
  149.         {
  150.                 UART_Send_Data(UART0,Data[i]);
  151.         }
  152.         #endif

  153.         #if 0
  154.     while(*Data)  
  155.     {  
  156.         UART_Send_Data(UART0, (unsigned char) *Data++);  
  157.     }
  158.         #endif
  159. }

  160. void send_UARTASCII(uint16_t Temp)
  161. {
  162.     uint8_t print_buf[16];
  163.     uint16_t i = 15, j;

  164.     *(print_buf + i) = '\0';
  165.     j = (uint16_t)Temp >> 31;
  166.     if(j)
  167.         (uint16_t) Temp = ~(uint16_t)Temp + 1;
  168.     do
  169.     {
  170.         i--;
  171.         *(print_buf + i) = '0' + (uint16_t)Temp % 10;
  172.         (uint16_t)Temp = (uint16_t)Temp / 10;
  173.     }
  174.     while((uint16_t)Temp != 0);
  175.     if(j)
  176.     {
  177.         i--;
  178.         *(print_buf + i) = '-';
  179.     }
  180.     send_UARTString(print_buf + i);
  181. }

  182. void PWMx_CHx_SetDuty(uint16_t ch , uint16_t d , uint16_t resolution)
  183. {
  184.         uint16_t res = 0 ;

  185.         SFRS = 1;
  186.         res = ((float) (MAKEWORD(PWM0PH,PWM0PL)+1)/resolution) * d;

  187.         switch(ch)
  188.         {
  189.                 case 2:
  190.             PWM0C2H = HIBYTE(res);
  191.             PWM0C2L = LOBYTE(res);
  192.                 break;
  193.         }


  194.     set_PWM0CON0_LOAD;
  195.     set_PWM0CON0_PWMRUN;       

  196. }


  197. void PWMx_Init(uint16_t ch , uint16_t uFrequency)
  198. {
  199.         uint32_t res = 0;

  200.         switch(ch)
  201.         {
  202.                 case 2:
  203.                 MFP_P03_PWM0_CH2;
  204.                 P03_PUSHPULL_MODE;
  205.                 break;
  206.         }
  207.        
  208.     PWM0_IMDEPENDENT_MODE;
  209.     PWM0_CLOCK_DIV_16;

  210. /*
  211.         PWM frequency   = Fpwm/((PWMPH,PWMPL)+1) = (24MHz/2)/(PWMPH,PWMPL)+1) = 20KHz
  212. */       

  213.         res = (SYS_CLOCK >> 4);                        // 2 ^ 4 = 16
  214.         res = res/uFrequency;
  215.         res = res - 1;       

  216.         SFRS = 1;
  217.     PWM0PH = HIBYTE(res);
  218.     PWM0PL = LOBYTE(res);
  219.        
  220.         set_flag(flag_reverse , Enable);       
  221.   
  222. }

  223. void GPIO_Init(void)
  224. {
  225. //        P03_PUSHPULL_MODE;               

  226. //        P30_PUSHPULL_MODE;       
  227. }

  228. void Breathing_LED(void)
  229. {
  230.         static uint16_t duty = 0;       
  231.         uint16_t resolution = 0;
  232.        
  233.         #if 1        // resolution : 100 , 15ms change duty , total duty change timing from 0 ~ 100 % (or 100% ~ 0%) will be 15*100 = 1500 ms
  234.         if ((get_tick() % 15) == 0)                // target : 1.5 sec (duty from 0 to 100) , 1.5 sec (duty from 100 to 0)
  235.         {
  236.                 resolution = PWM_RESOLUTION;
  237.        
  238.                 PWMx_CHx_SetDuty(PWM_CHANNEL , duty, resolution);

  239.                 if (is_flag_set(flag_reverse))
  240.                 {
  241.                         duty++;       
  242.                 }
  243.                 else
  244.                 {
  245.                         duty--;
  246.                 }

  247.                 if (duty == resolution)
  248.                 {
  249.                         set_flag(flag_reverse , Disable);                               
  250.                 }
  251.                 else if (duty == 0)
  252.                 {
  253.                         set_flag(flag_reverse , Enable);
  254.                 }
  255.         }
  256.         #else        // resolution : 1000 , 2ms change duty , total duty change timing from 0 ~ 100 % (or 100% ~ 0%) will be 2*1000 = 2000 ms
  257.         if ((get_tick() % 2) == 0)                // target : 2 sec (duty from 0 to 1000) , 2 sec (duty from 1000 to 0)
  258.         {
  259.                 resolution = 1000;
  260.                 PWMx_CHx_SetDuty(PWM_CHANNEL , duty, resolution);

  261.                 if (is_flag_set(flag_reverse))
  262.                 {
  263.                         duty++;       
  264.                 }
  265.                 else
  266.                 {
  267.                         duty--;
  268.                 }

  269.                 if (duty == resolution)
  270.                 {
  271.                         set_flag(flag_reverse , Disable);                               
  272.                 }
  273.                 else if (duty == 0)
  274.                 {
  275.                         set_flag(flag_reverse , Enable);
  276.                 }
  277.         }       

  278.         #endif       

  279. }


  280. void Timer0_IRQHandler(void)
  281. {
  282.        
  283.         tick_counter();

  284.         if ((get_tick() % 1000) == 0)
  285.         {
  286. //                P03 ^= 1;
  287.         }

  288.         Breathing_LED();

  289. }

  290. void Timer0_ISR(void) interrupt 1        // Vector [url=home.php?mod=space&uid=72445]@[/url]  0x0B
  291. {
  292.     TH0 = u8TH0_Tmp;
  293.     TL0 = u8TL0_Tmp;
  294.     clr_TCON_TF0;
  295.        
  296.         Timer0_IRQHandler();
  297. }

  298. void Timer0_Init(void)
  299. {
  300.         uint16_t res = 0;

  301.         ENABLE_TIMER0_MODE1;
  302.     TIMER0_FSYS_DIV12;
  303.        
  304.         u8TH0_Tmp = HIBYTE(TIMER_DIV12_VALUE_1ms_FOSC_240000);
  305.         u8TL0_Tmp = LOBYTE(TIMER_DIV12_VALUE_1ms_FOSC_240000);

  306.     TH0 = u8TH0_Tmp;
  307.     TL0 = u8TL0_Tmp;

  308.     ENABLE_TIMER0_INTERRUPT;                       //enable Timer0 interrupt
  309.     ENABLE_GLOBAL_INTERRUPT;                       //enable interrupts
  310.   
  311.     set_TCON_TR0;                                  //Timer0 run
  312. }


  313. //void Serial_ISR (void) interrupt 4
  314. //{
  315. //    _push_(SFRS);

  316. //    if (RI)
  317. //    {   
  318. //      uart0_receive_flag = 1;
  319. //      uart0_receive_data = SBUF;
  320. //      clr_SCON_RI;                                         // Clear RI (Receive Interrupt).
  321. //    }
  322. //    if  (TI)
  323. //    {
  324. //      if(!BIT_UART)
  325. //      {
  326. //          TI = 0;
  327. //      }
  328. //    }

  329. //    _pop_(SFRS);       
  330. //}


  331. void UART0_Init(void)
  332. {
  333.         MFP_P31_UART0_TXD;                              // UART0 TXD use P1.6
  334.         P31_QUASI_MODE;                                  // set P1.6 as Quasi mode for UART0 trasnfer
  335.         UART_Open(SYS_CLOCK,UART0_Timer3,115200);        // Open UART0 use timer1 as baudrate generate and baud rate = 115200
  336.         ENABLE_UART0_PRINTF;


  337. //        printf("UART0_Init\r\n");
  338. }

  339. void SYS_Init(void)
  340. {
  341.         FsysSelect(FSYS_HIRC);

  342.     ALL_GPIO_QUASI_MODE;
  343. //    ENABLE_GLOBAL_INTERRUPT;                // global enable bit       
  344. }

  345. void main (void)
  346. {
  347.     SYS_Init();

  348.     UART0_Init();
  349.         GPIO_Init();

  350.         PWMx_Init(PWM_CHANNEL , PWM_FREQ);

  351.         Timer0_Init();
  352.        
  353.     while(1)
  354.     {

  355.                
  356.     }
  357. }





heisexingqisi 发表于 2023-11-29 20:44 | 显示全部楼层
不停的修改占空比。
捉虫天师 发表于 2023-11-30 16:02 | 显示全部楼层
如何让呼吸灯呼吸的更加均匀呢。
EmmaTT 发表于 2023-12-6 10:46 来自手机 | 显示全部楼层
捉虫天师 发表于 2023-11-30 16:02
如何让呼吸灯呼吸的更加均匀呢。

占空比的步进值调小点
tpgf 发表于 2023-12-15 14:42 | 显示全部楼层
可以通过调节pwm的占空比调节呼吸灯的明暗吗
paotangsan 发表于 2023-12-15 15:31 | 显示全部楼层
最好还能根据外部的按键来灵活调整占空比或者是频率
wakayi 发表于 2023-12-15 19:19 | 显示全部楼层
呼吸灯只能通过pwm来进行控制吗
keaibukelian 发表于 2023-12-15 19:55 | 显示全部楼层
通过串接不同的电容 可以连接好多个呼吸灯吗
heimaojingzhang 发表于 2023-12-15 20:33 | 显示全部楼层
为什么呼吸灯可以做到慢慢的亮灭呢
guanjiaer 发表于 2023-12-15 21:11 | 显示全部楼层
一路pwm只能控制一路的呼吸灯吗
少女诗篇 发表于 2025-9-20 14:59 | 显示全部楼层
配置 ML51 定时器为 PWM 模式,设定周期固定,通过中断逐步增减占空比,循环变化使 LED 亮度渐变,实现呼吸灯效果。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

183

主题

2331

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部