[DemoCode下载] PWM通过串口指令调节风扇转速

[复制链接]
585|5
 楼主| huahuagg 发表于 2022-12-22 21:03 | 显示全部楼层 |阅读模式
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 1 $
  5. * $Date: 19/07/24 8:14p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Use Mini51 PWM Channel 0 (P2.2) to control 4-wire PWM fan speed
  7. *           and use Timer 0 external capture pin (P3.2) to detect fan speed
  8. *           in RPM
  9. *
  10. * @note
  11. * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "Mini51Series.h"

  15. /*---------------------------------------------------------------------------*/
  16. /* Define                                                                    */
  17. /*---------------------------------------------------------------------------*/
  18. #define Fan_Pole        4

  19. /*---------------------------------------------------------------------------*/
  20. /* Global variables                                                          */
  21. /*---------------------------------------------------------------------------*/
  22. volatile uint8_t g_u8DetectFlag;
  23. uint8_t g_u8PWMDuty;

  24. /*---------------------------------------------------------------------------*/
  25. /* Functions                                                                 */
  26. /*---------------------------------------------------------------------------*/
  27. void SYS_Init(void);
  28. void UART_Init(void);
  29. void TMR0_Init(void);
  30. void PWM_Init(void);
  31. void Delay_mS(uint32_t m_second);

  32. void TMR0_IRQHandler(void)
  33. {
  34.     uint32_t u32_FanRPM;

  35.     /* Stop Timer 0 */
  36.     TIMER_Stop(TIMER0);

  37.     /* Calculate RPM = (Timer 0 Clock Source Frequency / (Fan_Pole * Timer 0 Capture Value)) * 60 */
  38.     u32_FanRPM = (22118400 / (Fan_Pole * TIMER_GetCaptureData(TIMER0))) * 60;
  39.     printf("%d RPM.\n", u32_FanRPM);

  40.     /* Clear Timer 0 Capture interrupt flag */
  41.     TIMER_ClearCaptureIntFlag(TIMER0);

  42.     /* Set Detect done flag*/
  43.     g_u8DetectFlag = 1;
  44. }

  45. void SYS_Init(void)
  46. {
  47.     /*---------------------------------------------------------------------------------------------------------*/
  48.     /* Init System Clock                                                                                       */
  49.     /*---------------------------------------------------------------------------------------------------------*/

  50.     /* Enable Internal RC clock */
  51.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  52.     /* Waiting for IRC22M clock ready */
  53.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  54.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  55.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  56.     /* Update System Core Clock */
  57.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and CycylesPerUs automatically. */
  58.     SystemCoreClockUpdate();

  59.     /* Enable UART module clock */
  60.     CLK_EnableModuleClock(UART_MODULE);

  61.     /* Enable Timer 0 module clock */
  62.     CLK_EnableModuleClock(TMR0_MODULE);

  63.     /* Enable Timer 1 module clock */
  64.     CLK_EnableModuleClock(TMR1_MODULE);

  65.     /* Enable PWM module clock */
  66.     CLK_EnableModuleClock(PWM01_MODULE);

  67.     /* Select UART module clock source */
  68.     CLK_SetModuleClock(UART_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));

  69.     /* Select Timer 0 module clock source */
  70.     CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HIRC, 0);

  71.     /* Select Timer 1 module clock source */
  72.     CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1_S_HIRC, 0);

  73.     /* Select PWM module clock source */
  74.     CLK_SetModuleClock(PWM01_MODULE, CLK_CLKSEL1_PWM01_S_HCLK, 0);

  75.     /*---------------------------------------------------------------------------------------------------------*/
  76.     /* Init I/O Multi-function                                                                                 */
  77.     /*---------------------------------------------------------------------------------------------------------*/
  78.     /* Set P1 multi-function pins for UART RXD, TXD */
  79.     SYS->P1_MFP = (SYS->P1_MFP & ~(SYS_MFP_P12_Msk | SYS_MFP_P13_Msk)) | (SYS_MFP_P12_RXD | SYS_MFP_P13_TXD);

  80.     /* Set P3 multi function pin for Timer 0 capture pin */
  81.     SYS->P3_MFP = (SYS->P3_MFP & ~SYS_MFP_P32_Msk) | SYS_MFP_P32_T0EX;

  82.     /* Set P2 multi function pin for PWM Channel 0 pin */
  83.     SYS->P2_MFP = (SYS->P2_MFP & ~SYS_MFP_P22_Msk) | SYS_MFP_P22_PWM0;
  84. }

  85. void UART_Init(void)
  86. {
  87.     /*---------------------------------------------------------------------------------------------------------*/
  88.     /* Init UART                                                                                               */
  89.     /*---------------------------------------------------------------------------------------------------------*/
  90.     /* Reset IP */
  91.     SYS_ResetModule(UART_RST);

  92.     /* Configure UART and set UART Baudrate */
  93.     UART_Open(UART, 115200);
  94. }

  95. void TMR0_Init(void)
  96. {
  97.     /*---------------------------------------------------------------------------------------------------------*/
  98.     /* Init Timer 0                                                                                            */
  99.     /*---------------------------------------------------------------------------------------------------------*/
  100.     /* Reset IP */
  101.     SYS_ResetModule(TMR0_RST);

  102.     /* Give a dummy target frequency here. Will over write capture resolution with macro */
  103.     TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000000);

  104.     /* Update prescale to set proper resolution */
  105.     TIMER_SET_PRESCALE_VALUE(TIMER0, 0);

  106.     /* Set compare value as large as possible, so don't need to worry about counter overrun too frequently */
  107.     TIMER_SET_CMP_VALUE(TIMER0, 0xFFFFFF);

  108.     /* Configure Timer 0 trigger counting mode and level change trigger.
  109.              The high to low transition on Timer 0 external capture pin is detected to reset TDR as 0
  110.              and then starts counting, while low to high transition stops counting. */
  111.     TIMER_EnableCapture(TIMER0, TIMER_CAPTURE_TRIGGER_COUNTING_MODE, TIMER_CAPTURE_FALLING_THEN_RISING_EDGE);

  112.     /* Enable T0EX debounce function */
  113.     TIMER0->TEXCON |= TIMER_TEXCON_TEXDB_Msk;

  114.     /* Enable timer interrupt */
  115.     TIMER_EnableCaptureInt(TIMER0);
  116.     NVIC_EnableIRQ(TMR0_IRQn);
  117. }

  118. void PWM_Init(void)
  119. {
  120.     /*---------------------------------------------------------------------------------------------------------*/
  121.     /* Init PWM Channel 0                                                                                      */
  122.     /*---------------------------------------------------------------------------------------------------------*/
  123.     /* Reset IP */
  124.     SYS_ResetModule(PWM_RST);

  125.     /* Set PWM Channel 0 frequency to 25 kHz and initial duty 100% */
  126.     PWM_ConfigOutputChannel(PWM, 0, 25000, 100);

  127.     /* Enable PWM Channel 0 output */
  128.     PWM_EnableOutput(PWM, BIT0);
  129. }

  130. void Delay_mS(uint32_t m_second)
  131. {
  132.     uint32_t i;

  133.     for (i = 0; i < m_second; i++)
  134.     {
  135.         TIMER_Delay(TIMER1, 1000);
  136.     }
  137. }

  138. int main(void)
  139. {
  140.     uint8_t u8Action;

  141.     /* Unlock protected registers */
  142.     SYS_UnlockReg();

  143.     /* Init System, IP clock and multi-function I/O */
  144.     SYS_Init();

  145.     /* Lock protected registers */
  146.     SYS_LockReg();

  147.     /* Init UART for printf */
  148.     UART_Init();

  149.     /* Init Timer 0 */
  150.     TMR0_Init();

  151.     /* Init PWM Channel 0 */
  152.     PWM_Init();

  153.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
  154.     printf("+-----------------------------------------------------------------+\n");
  155.     printf("|    4-wire PWM Fan Control Sample Code                           |\n");
  156.     printf("|    Use PWM Channel 0 to control fan speed                       |\n");
  157.     printf("|    and use Timer 0 Capture mode to detect fan speed in RPM.     |\n");
  158.     printf("|    Please connect PWM Channel 0 (P2.2) to fan control pin       |\n");
  159.     printf("|    and connect Timer 0 external capture pin (P3.2) to fan       |\n");
  160.     printf("|    sense pin.                                                   |\n");
  161.     printf("+-----------------------------------------------------------------+\n");

  162.     /* Test maximum fan speed */
  163.     /* Start PWM Channel 0 */
  164.     PWM_Start(PWM, BIT0);
  165.     /* Wait 3 seconds */
  166.     Delay_mS(3000);
  167.     /* Start Timer 0 to detect the time which fan takes when rotating one round */
  168.     g_u8DetectFlag = 0;
  169.     printf("The maximum fan speed is ");
  170.     TIMER_Start(TIMER0);

  171.     while (!g_u8DetectFlag);

  172.     /* Test maximum fan speed */
  173.     /* Force PWM Channel 0 output low */
  174.     PWM->PHCHG = PWM->PHCHGNXT & ~(PWM_PHCHGNXT_PWM0_Msk | PWM_PHCHGNXT_D0_Msk);
  175.     /* Wait 3 seconds */
  176.     Delay_mS(3000);
  177.     /* Start Timer 0 to detect the time which fan takes when rotating one round */
  178.     g_u8DetectFlag = 0;
  179.     printf("The mimimum fan speed is ");
  180.     TIMER_Start(TIMER0);

  181.     while (!g_u8DetectFlag);

  182.     /* Current PWM duty */
  183.     g_u8PWMDuty = 60;

  184.     while (1)
  185.     {
  186.         printf("\n\nCurrent PWM duty is %d%%, please enter your action.\n", g_u8PWMDuty);
  187.         printf("(1: Increase 10%%; 2: Increase 1%%; 3: Decrease 10%%; 4: Decrease 1%%)\n");
  188.         u8Action = getchar();
  189.         printf("%c\n", u8Action);

  190.         switch (u8Action)
  191.         {
  192.             case '1':
  193.             {
  194.                 /* Increase PWM duty 10% */
  195.                 (g_u8PWMDuty > 90) ? (g_u8PWMDuty = 100) : (g_u8PWMDuty += 10);

  196.                 break;
  197.             }

  198.             case '2':
  199.             {
  200.                 /* Increase PWM duty 1% */
  201.                 (g_u8PWMDuty > 99) ? (g_u8PWMDuty = 100) : (g_u8PWMDuty++);

  202.                 break;
  203.             }

  204.             case '3':
  205.             {
  206.                 /* Decrease PWM duty 10% */
  207.                 (g_u8PWMDuty < 10) ? (g_u8PWMDuty = 0) : (g_u8PWMDuty -= 10);

  208.                 break;
  209.             }

  210.             case '4':
  211.             {
  212.                 /* Decrease PWM duty 1% */
  213.                 (g_u8PWMDuty < 1) ? (g_u8PWMDuty = 0) : (g_u8PWMDuty--);

  214.                 break;
  215.             }

  216.             default:
  217.             {
  218.                 continue;
  219.             }
  220.         }

  221.         /* Set PWM Channel 0 frequency and duty */
  222.         if (g_u8PWMDuty > 0)
  223.         {
  224.             PWM->PHCHG |= PWM_PHCHGNXT_PWM0_Msk;
  225.             PWM_ConfigOutputChannel(PWM, 0, 25000, g_u8PWMDuty);
  226.         }
  227.         else
  228.             PWM->PHCHG = PWM->PHCHGNXT & ~(PWM_PHCHGNXT_PWM0_Msk | PWM_PHCHGNXT_D0_Msk);

  229.         /* Wait 3 seconds */
  230.         printf("Changing... ");
  231.         Delay_mS(3000);
  232.         /* Start Timer 0 to detect the time which fan takes when rotating one round */
  233.         g_u8DetectFlag = 0;
  234.         printf("Current fan speed is ");
  235.         TIMER_Start(TIMER0);

  236.         while (!g_u8DetectFlag);
  237.     }
  238. }

  239. /*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/


yiyigirl2014 发表于 2022-12-23 09:39 | 显示全部楼层
PWM调节还是挺好的。
小夏天的大西瓜 发表于 2022-12-24 21:06 | 显示全部楼层
随之知识的还不断深入还是感觉自己学习使用出来的比较少,PWM经典电压调节的输出控制
xinpian101 发表于 2022-12-25 15:25 | 显示全部楼层
修改占空比实现调速。
AdaMaYun 发表于 2022-12-27 10:47 | 显示全部楼层
PWM 的功能可实现性还是挺多的
LOVEEVER 发表于 2022-12-27 15:04 | 显示全部楼层
PWM修改占空比实现电压调速,非常使用
您需要登录后才可以回帖 登录 | 注册

本版积分规则

160

主题

1437

帖子

2

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