- /**************************************************************************//**
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
- * $Revision: 1 $
- * $Date: 19/07/24 8:14p $
- * [url=home.php?mod=space&uid=247401]@brief[/url] Use Mini51 PWM Channel 0 (P2.2) to control 4-wire PWM fan speed
- * and use Timer 0 external capture pin (P3.2) to detect fan speed
- * in RPM
- *
- * @note
- * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
- ******************************************************************************/
- #include <stdio.h>
- #include "Mini51Series.h"
- /*---------------------------------------------------------------------------*/
- /* Define */
- /*---------------------------------------------------------------------------*/
- #define Fan_Pole 4
- /*---------------------------------------------------------------------------*/
- /* Global variables */
- /*---------------------------------------------------------------------------*/
- volatile uint8_t g_u8DetectFlag;
- uint8_t g_u8PWMDuty;
- /*---------------------------------------------------------------------------*/
- /* Functions */
- /*---------------------------------------------------------------------------*/
- void SYS_Init(void);
- void UART_Init(void);
- void TMR0_Init(void);
- void PWM_Init(void);
- void Delay_mS(uint32_t m_second);
- void TMR0_IRQHandler(void)
- {
- uint32_t u32_FanRPM;
- /* Stop Timer 0 */
- TIMER_Stop(TIMER0);
- /* Calculate RPM = (Timer 0 Clock Source Frequency / (Fan_Pole * Timer 0 Capture Value)) * 60 */
- u32_FanRPM = (22118400 / (Fan_Pole * TIMER_GetCaptureData(TIMER0))) * 60;
- printf("%d RPM.\n", u32_FanRPM);
- /* Clear Timer 0 Capture interrupt flag */
- TIMER_ClearCaptureIntFlag(TIMER0);
- /* Set Detect done flag*/
- g_u8DetectFlag = 1;
- }
- void SYS_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init System Clock */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Enable Internal RC clock */
- CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
- /* Waiting for IRC22M clock ready */
- CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
- /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
- CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
- /* Update System Core Clock */
- /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and CycylesPerUs automatically. */
- SystemCoreClockUpdate();
- /* Enable UART module clock */
- CLK_EnableModuleClock(UART_MODULE);
- /* Enable Timer 0 module clock */
- CLK_EnableModuleClock(TMR0_MODULE);
- /* Enable Timer 1 module clock */
- CLK_EnableModuleClock(TMR1_MODULE);
- /* Enable PWM module clock */
- CLK_EnableModuleClock(PWM01_MODULE);
- /* Select UART module clock source */
- CLK_SetModuleClock(UART_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));
- /* Select Timer 0 module clock source */
- CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HIRC, 0);
- /* Select Timer 1 module clock source */
- CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1_S_HIRC, 0);
- /* Select PWM module clock source */
- CLK_SetModuleClock(PWM01_MODULE, CLK_CLKSEL1_PWM01_S_HCLK, 0);
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init I/O Multi-function */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Set P1 multi-function pins for UART RXD, TXD */
- SYS->P1_MFP = (SYS->P1_MFP & ~(SYS_MFP_P12_Msk | SYS_MFP_P13_Msk)) | (SYS_MFP_P12_RXD | SYS_MFP_P13_TXD);
- /* Set P3 multi function pin for Timer 0 capture pin */
- SYS->P3_MFP = (SYS->P3_MFP & ~SYS_MFP_P32_Msk) | SYS_MFP_P32_T0EX;
- /* Set P2 multi function pin for PWM Channel 0 pin */
- SYS->P2_MFP = (SYS->P2_MFP & ~SYS_MFP_P22_Msk) | SYS_MFP_P22_PWM0;
- }
- void UART_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init UART */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Reset IP */
- SYS_ResetModule(UART_RST);
- /* Configure UART and set UART Baudrate */
- UART_Open(UART, 115200);
- }
- void TMR0_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init Timer 0 */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Reset IP */
- SYS_ResetModule(TMR0_RST);
- /* Give a dummy target frequency here. Will over write capture resolution with macro */
- TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000000);
- /* Update prescale to set proper resolution */
- TIMER_SET_PRESCALE_VALUE(TIMER0, 0);
- /* Set compare value as large as possible, so don't need to worry about counter overrun too frequently */
- TIMER_SET_CMP_VALUE(TIMER0, 0xFFFFFF);
- /* Configure Timer 0 trigger counting mode and level change trigger.
- The high to low transition on Timer 0 external capture pin is detected to reset TDR as 0
- and then starts counting, while low to high transition stops counting. */
- TIMER_EnableCapture(TIMER0, TIMER_CAPTURE_TRIGGER_COUNTING_MODE, TIMER_CAPTURE_FALLING_THEN_RISING_EDGE);
- /* Enable T0EX debounce function */
- TIMER0->TEXCON |= TIMER_TEXCON_TEXDB_Msk;
- /* Enable timer interrupt */
- TIMER_EnableCaptureInt(TIMER0);
- NVIC_EnableIRQ(TMR0_IRQn);
- }
- void PWM_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init PWM Channel 0 */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Reset IP */
- SYS_ResetModule(PWM_RST);
- /* Set PWM Channel 0 frequency to 25 kHz and initial duty 100% */
- PWM_ConfigOutputChannel(PWM, 0, 25000, 100);
- /* Enable PWM Channel 0 output */
- PWM_EnableOutput(PWM, BIT0);
- }
- void Delay_mS(uint32_t m_second)
- {
- uint32_t i;
- for (i = 0; i < m_second; i++)
- {
- TIMER_Delay(TIMER1, 1000);
- }
- }
- int main(void)
- {
- uint8_t u8Action;
- /* Unlock protected registers */
- SYS_UnlockReg();
- /* Init System, IP clock and multi-function I/O */
- SYS_Init();
- /* Lock protected registers */
- SYS_LockReg();
- /* Init UART for printf */
- UART_Init();
- /* Init Timer 0 */
- TMR0_Init();
- /* Init PWM Channel 0 */
- PWM_Init();
- printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
- printf("+-----------------------------------------------------------------+\n");
- printf("| 4-wire PWM Fan Control Sample Code |\n");
- printf("| Use PWM Channel 0 to control fan speed |\n");
- printf("| and use Timer 0 Capture mode to detect fan speed in RPM. |\n");
- printf("| Please connect PWM Channel 0 (P2.2) to fan control pin |\n");
- printf("| and connect Timer 0 external capture pin (P3.2) to fan |\n");
- printf("| sense pin. |\n");
- printf("+-----------------------------------------------------------------+\n");
- /* Test maximum fan speed */
- /* Start PWM Channel 0 */
- PWM_Start(PWM, BIT0);
- /* Wait 3 seconds */
- Delay_mS(3000);
- /* Start Timer 0 to detect the time which fan takes when rotating one round */
- g_u8DetectFlag = 0;
- printf("The maximum fan speed is ");
- TIMER_Start(TIMER0);
- while (!g_u8DetectFlag);
- /* Test maximum fan speed */
- /* Force PWM Channel 0 output low */
- PWM->PHCHG = PWM->PHCHGNXT & ~(PWM_PHCHGNXT_PWM0_Msk | PWM_PHCHGNXT_D0_Msk);
- /* Wait 3 seconds */
- Delay_mS(3000);
- /* Start Timer 0 to detect the time which fan takes when rotating one round */
- g_u8DetectFlag = 0;
- printf("The mimimum fan speed is ");
- TIMER_Start(TIMER0);
- while (!g_u8DetectFlag);
- /* Current PWM duty */
- g_u8PWMDuty = 60;
- while (1)
- {
- printf("\n\nCurrent PWM duty is %d%%, please enter your action.\n", g_u8PWMDuty);
- printf("(1: Increase 10%%; 2: Increase 1%%; 3: Decrease 10%%; 4: Decrease 1%%)\n");
- u8Action = getchar();
- printf("%c\n", u8Action);
- switch (u8Action)
- {
- case '1':
- {
- /* Increase PWM duty 10% */
- (g_u8PWMDuty > 90) ? (g_u8PWMDuty = 100) : (g_u8PWMDuty += 10);
- break;
- }
- case '2':
- {
- /* Increase PWM duty 1% */
- (g_u8PWMDuty > 99) ? (g_u8PWMDuty = 100) : (g_u8PWMDuty++);
- break;
- }
- case '3':
- {
- /* Decrease PWM duty 10% */
- (g_u8PWMDuty < 10) ? (g_u8PWMDuty = 0) : (g_u8PWMDuty -= 10);
- break;
- }
- case '4':
- {
- /* Decrease PWM duty 1% */
- (g_u8PWMDuty < 1) ? (g_u8PWMDuty = 0) : (g_u8PWMDuty--);
- break;
- }
- default:
- {
- continue;
- }
- }
- /* Set PWM Channel 0 frequency and duty */
- if (g_u8PWMDuty > 0)
- {
- PWM->PHCHG |= PWM_PHCHGNXT_PWM0_Msk;
- PWM_ConfigOutputChannel(PWM, 0, 25000, g_u8PWMDuty);
- }
- else
- PWM->PHCHG = PWM->PHCHGNXT & ~(PWM_PHCHGNXT_PWM0_Msk | PWM_PHCHGNXT_D0_Msk);
- /* Wait 3 seconds */
- printf("Changing... ");
- Delay_mS(3000);
- /* Start Timer 0 to detect the time which fan takes when rotating one round */
- g_u8DetectFlag = 0;
- printf("Current fan speed is ");
- TIMER_Start(TIMER0);
- while (!g_u8DetectFlag);
- }
- }
- /*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/
|