【沁恒微CH32V307评估板试用体验】利用TIM1的输出通道产生50Hz的正弦波 - RISC-V MCU技术社区 - 电子技术william hill官网 - 广受欢迎的专业电子william hill官网 - 威廉希尔官方网站
分享 收藏 返回

Youzhiyu 关注 私信
[文章]

【沁恒微CH32V307评估板试用体验】利用TIM1的输出通道产生50Hz的正弦波

实验视频:   https://yingsheng.elecfans.com/s ... NPlzqxSDkGxG3iFAdpA
    本次实验是利用CH32V307评估板产生一个50Hz的正弦波。根据PWM波基本原理可知,正弦波可以用SPWM等效得到。因此,本实验就是根据PWM调整原理来产生SPWM,然后对输出的SPWM进行滤波即可得到期望的正弦波。
    SWPM调制原理是利用调整信号(期望输出的正弦波)与载波(锯齿波)比较得到对应的SPWM,利用改SPWM就可以得到对应的50Hz正弦波。
1:参数调制信号
    PWM调整原理是利用正弦信号与锯齿波比较,根据比较结果输出PWM波。因此首先需要产生一个正弦波。在MCU中,一个正弦波可以用一组等宽不等幅的脉冲序列表示。每个脉冲的幅值可以利用函数生成,如下:
  1. //point 一个周期内的点数
  2. //maxnum 正弦波最大值
  3. #define  PI  3.1415926
  4. #define  NPoint        360
  5. #define  AmplitudeMax  1000

  6. uint16_t sinData[NPoint];
  7. uint16_t PlusD_cnt=0;

  8. void get_sin_tab( uint16_t point , uint16_t maxnum)
  9. {
  10.     uint16_t i = 0, k = 0;
  11.     float hd = 0.0;   //弧度
  12.     float fz = 0.0;   //峰值
  13.     uint16_t tem = 0;
  14.     hd = (2*PI)/point; // 2π内每等分间隔的幅度大小
  15.     k = maxnum/2;    //最大值一半,单片机没有负电压,设置水平线位置
  16.     for( i = 0; i < point; i++ )
  17.     {
  18.         fz =(float)(k*sin(hd*i))+k;
  19.         tem = ( uint16_t )fz ;
  20.         //将产生的数据通过串口输出
  21.         printf("%d
  22. ",tem);
  23.         sinData = tem;
  24.     }
  25. }

在主函数中,调用该函数即可生成N等份的N个脉冲序列,且每一个脉冲的幅值都存入sinData 中。
本次实验准备实验18KHz的锯齿波对50Hz的正弦进行调制得到SPWM波。因此N=18K/50=360个采样点。调用函数为:
  1. get_sin_tab(NPoint,AmplitudeMax);

利用串口波形监视工具,可以得到采样数据形成的波形为正弦,如下图:

注意:此处需要使用到数学库函数sin(),所以需要在MRS环境的工程项目属性中添加数学库。如下图:

2:产生固定占空比的PWM,PWM频率18KHz,及产生载波锯齿波。

  1. /* PWM Output Mode Definition */
  2. #define PWM_MODE1   0
  3. #define PWM_MODE2   1
  4. /* PWM Output Mode Selection */
  5. #define PWM_MODE PWM_MODE1
  6. //#define PWM_MODE PWM_MODE2

  7. /* 声明中断函数属性 */
  8. void TIM1_CC_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  9. void TIM1_PWMOut_Init( u16 arr, u16 psc, u16 ccp )
  10. {
  11.     GPIO_InitTypeDef GPIO_InitStructure={0};
  12.     TIM_OCInitTypeDef TIM_OCInitStructure={0};
  13.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
  14.     NVIC_InitTypeDef NVIC_InitStruct;

  15.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

  16.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  17.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  18.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  19.     GPIO_Init( GPIOA, &GPIO_InitStructure );

  20.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  21.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  22.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  23.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  24.     TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);

  25. #if (PWM_MODE == PWM_MODE1)
  26.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  27. #elif (PWM_MODE == PWM_MODE2)
  28.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  29. #endif

  30.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  31.     TIM_OCInitStructure.TIM_Pulse = ccp;
  32.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  33.     TIM_OC1Init( TIM1, &TIM_OCInitStructure );

  34.     TIM_CtrlPWMOutputs(TIM1, ENABLE );
  35.     TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );
  36.     TIM_ARRPreloadConfig( TIM1, ENABLE );

  37.     TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
  38.     //中断优先级NVIC设置:中断通道、抢占优先级、响应优先级、使能
  39.     NVIC_InitStruct.NVIC_IRQChannel = TIM1_CC_IRQn;
  40.     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  41.     NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  42.     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  43.     NVIC_Init(&NVIC_InitStruct);

  44.     TIM_Cmd( TIM1, ENABLE );
  45. }

3:在比较匹配中断函数中,更改比较寄存器CCRx的值,实现占空比按正弦规律变换,其宽度用生成的正弦N等份幅值表示。
  1. void TIM1_CC_IRQHandler(void)
  2. {
  3.     if(TIM_GetITStatus(TIM1,TIM_IT_CC1)==SET)
  4.     {
  5.         TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);
  6.         TIM_SetCompare1(TIM1, sinData[PlusD_cnt]);
  7.         PlusD_cnt++;
  8.         if(PlusD_cnt >= NPoint)
  9.             PlusD_cnt = 0;
  10.     }
  11. }

4:在主函数中调用,实现SPWM输出。
  1. int main(void)
  2. {
  3.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  4.         Delay_Init();
  5.         USART_Printf_Init(115200);
  6.         printf("SystemClk:%d
  7. ",SystemCoreClock);
  8.         printf("This is printf example
  9. ");
  10.         get_sin_tab(NPoint,AmplitudeMax);
  11.         //sysclk = 72MHz psc = 3 ,4分频18kHz, ARR=999
  12.         TIM1_PWMOut_Init( 999, 3, 499 );

  13.         while(1)
  14.        {
  15.            Delay_Ms(2000);
  16.         }
  17. }




更多回帖

×
发帖