沁恒微电子 ch32v307 RISC-V 开发板试用
实验视频: https://yingsheng.elecfans.com/s ... NPlzqxSDkGxG3iFAdpA
本次实验是利用CH32V307评估板产生一个50Hz的正弦波。根据PWM波基本原理可知,正弦波可以用SPWM等效得到。因此,本实验就是根据PWM调整原理来产生SPWM,然后对输出的SPWM进行滤波即可得到期望的正弦波。
SWPM调制原理是利用调整信号(期望输出的正弦波)与载波(锯齿波)比较得到对应的SPWM,利用改SPWM就可以得到对应的50Hz正弦波。
1:参数调制信号
PWM调整原理是利用正弦信号与锯齿波比较,根据比较结果输出PWM波。因此首先需要产生一个正弦波。在MCU中,一个正弦波可以用一组等宽不等幅的脉冲序列表示。每个脉冲的幅值可以利用函数生成,如下:
- //point 一个周期内的点数
- //maxnum 正弦波最大值
- #define PI 3.1415926
- #define NPoint 360
- #define AmplitudeMax 1000
- uint16_t sinData[NPoint];
- uint16_t PlusD_cnt=0;
- void get_sin_tab( uint16_t point , uint16_t maxnum)
- {
- uint16_t i = 0, k = 0;
- float hd = 0.0; //弧度
- float fz = 0.0; //峰值
- uint16_t tem = 0;
- hd = (2*PI)/point; // 2π内每等分间隔的幅度大小
- k = maxnum/2; //最大值一半,单片机没有负电压,设置水平线位置
- for( i = 0; i < point; i++ )
- {
- fz =(float)(k*sin(hd*i))+k;
- tem = ( uint16_t )fz ;
- //将产生的数据通过串口输出
- printf("%d
- ",tem);
- sinData = tem;
- }
- }
在主函数中,调用该函数即可生成N等份的N个脉冲序列,且每一个脉冲的幅值都存入sinData 中。
本次实验准备实验18KHz的锯齿波对50Hz的正弦进行调制得到SPWM波。因此N=18K/50=360个采样点。调用函数为:
- get_sin_tab(NPoint,AmplitudeMax);
利用串口波形监视工具,可以得到采样数据形成的波形为正弦,如下图:
注意:此处需要使用到数学库函数sin(),所以需要在MRS环境的工程项目属性中添加数学库。如下图:
2:产生固定占空比的PWM,PWM频率18KHz,及产生载波锯齿波。
- /* PWM Output Mode Definition */
- #define PWM_MODE1 0
- #define PWM_MODE2 1
- /* PWM Output Mode Selection */
- #define PWM_MODE PWM_MODE1
- //#define PWM_MODE PWM_MODE2
- /* 声明中断函数属性 */
- void TIM1_CC_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- void TIM1_PWMOut_Init( u16 arr, u16 psc, u16 ccp )
- {
- GPIO_InitTypeDef GPIO_InitStructure={0};
- TIM_OCInitTypeDef TIM_OCInitStructure={0};
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init( GPIOA, &GPIO_InitStructure );
- TIM_TimeBaseInitStructure.TIM_Period = arr;
- TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);
- #if (PWM_MODE == PWM_MODE1)
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- #elif (PWM_MODE == PWM_MODE2)
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
- #endif
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = ccp;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OC1Init( TIM1, &TIM_OCInitStructure );
- TIM_CtrlPWMOutputs(TIM1, ENABLE );
- TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );
- TIM_ARRPreloadConfig( TIM1, ENABLE );
- TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
- //中断优先级NVIC设置:中断通道、抢占优先级、响应优先级、使能
- NVIC_InitStruct.NVIC_IRQChannel = TIM1_CC_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStruct);
- TIM_Cmd( TIM1, ENABLE );
- }
3:在比较匹配中断函数中,更改比较寄存器CCRx的值,实现占空比按正弦规律变换,其宽度用生成的正弦N等份幅值表示。
- void TIM1_CC_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM1,TIM_IT_CC1)==SET)
- {
- TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);
- TIM_SetCompare1(TIM1, sinData[PlusD_cnt]);
- PlusD_cnt++;
- if(PlusD_cnt >= NPoint)
- PlusD_cnt = 0;
- }
- }
4:在主函数中调用,实现SPWM输出。
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d
- ",SystemCoreClock);
- printf("This is printf example
- ");
- get_sin_tab(NPoint,AmplitudeMax);
- //sysclk = 72MHz psc = 3 ,4分频18kHz, ARR=999
- TIM1_PWMOut_Init( 999, 3, 499 );
- while(1)
- {
- Delay_Ms(2000);
- }
- }
更多回帖
长按上方图片保存到相册