本帖最后由 王小琪 于 2020-11-10 22:39 编辑
目的:如题,进行CH32V103开发板的PWM输出实验,PWM输出应用到led上就是灯逐渐变亮或者变暗,因为改变了占空比即改变了电压的大小,通过led的电流也随之改变了。PWM运动到电机驱动上就可以进行调速的应用,这个时候一般是用示波器来测量,但是我相信大多数人周围没有这个条件,所以这次就通过观察led的明暗来学习PWM输出。
1.硬件分析
首先还是led,用一个或者两个都可以,我们继续看原理图如下:
然后因为要用定时器输出PWM,所以要了解定时器的知识,如果是用定时器做定时中断的话,那么定时器就是单片机的内部资源,就不用在硬件上做处理了。但是PWM输出不一样,需要输出电平,所以我们要继续对定时器做更深入一点儿的了解。
通过下图我们可以看到TIM1有4个通道(同理另外的TIM2 TIM3 TIM4也应该有4个通道),对应的IO口分别是PA8 PA9 PA10 PA11,所以我们应该将我们要用到的led一端连接到其中一个IO口,然后进行代码的编写。
我们为了配合软件,将LED1和PA8连接在一起。
2.软件分析
代码层面的话,因为MounRiver Studio可以对CH32V103单片机生成对应的模板,所以只需要修改led.c,led.h,pwm.c,pwm.h,main.c文件即可。下面稍微看一下pwm.c文件和main.c文件
pwm.c文件主要是对定时器的pwm设置,这些如果是STM32的话可以用CUBEMX生成,但是现在并不可以,还是多看几遍吧,书读百遍,其义自见,源码也是,读多了自然就熟悉了。
其次是main.c文件,代码和官方的代码是完全一样的,但是这个板子的串口好像有点儿问题,所以其实里面有两句关于串口配置以及打印其实是没啥用的,但我也懒得去改了。主要看一下“TIM1_PWMOut_Init( 899, 0, 500 );”和“TIM_SetCompare1(TIM1,pwmval);”这两句一个是设置频率,一个是改变占空比,其实主函数里面的内容也很少。
void TIM1_PWMOut_Init( u16 arr, u16 psc, u16 ccp )
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );//使能GPIOA外设时钟和TIM1时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //配置PA8引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置输出速度:50MHz
GPIO_Init( GPIOA, &GPIO_InitStructure ); //GPIO初始化
TIM_TimeBaseInitStructure.TIM_Period = arr; //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
TIM_TimeBaseInitStructure.TIM_Prescaler = psc; //指定用于划分TIM时钟的预分频器值。
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM计数模式,向上计数模式
TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //指定TIM模式
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//指定TIM输出比较状态,即使能比较输出
TIM_OCInitStructure.TIM_Pulse = ccp; //指定要加载到捕获比较寄存器中的脉冲值。
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //指定输出极性。
TIM_OC1Init( TIM1, &TIM_OCInitStructure ); //根据TIM_OCInitStruct中指定的参数初始化TIM1 Channel1。
TIM_CtrlPWMOutputs(TIM1, ENABLE ); //启用定时器1PWM输出
TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );//使能CCR1上的TIM1外设预加载寄存器
TIM_ARRPreloadConfig( TIM1, ENABLE ); //使能ARR上TIM1外设预加载寄存器
TIM_Cmd( TIM1, ENABLE ); //使能TIM1
}
int main(void)
{
u16 pwmval=0;
u8 a=1;
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
TIM1_PWMOut_Init( 899, 0, 500 );
while(1)
{
Delay_Ms(10);
if(a) pwmval++;
else pwmval--;
if(pwmval>300) a=0;
if(pwmval==0) a=1;
TIM_SetCompare1(TIM1,pwmval); //设置TIM1捕获比较1寄存器值,,用于修改占空比
}
}
3.环境搭建
硬件软件都配置好了,只需要用WCH-LINK和开发板连接起来将代码下载进去,观察现象即可。可以看到LED1在亮灭之间循环,即呼吸灯的效果。
|