一、由来
因单片机(STC8G1K08)选型问题,项目需要4路pwm输出,但实际只有3路,大写的尴尬!!!!
补充点题外话
STC8G1K08的PWM采用pca来实现,也比较坑
如果采用系统主频作为时钟源,只能做固定的分频
而采用定时器作为时钟,才能实现自定义频率,但是我的定时器用完了,漂亮!!!!
二、解决
该单片机有三个定时器,用一个定时器来做模拟pwm,因主频24M,基本能满足要求
1. 主要原理
首先定时器计时设置为高电平的时间
定时器中断触发,再次设置定时器计时为低电平时间
定时器中断触发,再次设置定时器计时为高电平时间,无线循环
在中断处理中,根据高电平还是低电平的时间,设置IO输出高或者低
2. 代码实现
以下代码采用定时器1来实现
2.1 定义高电平和低电平的变量
// [0] = 高电平时间
// [1] = 低电平时间
u16 g_u16Pwm4[2]={25535, 45535};
bit s_u1Index = 0;
2.2 初始化定时器,最快速度工作,并打开中断
void Timer_config1(void)
{
TIM_InitTypeDef TIM_InitStructure; //结构定义
TIM_InitStructure.TIM_Mode = TIM_16Bit; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 0; //初值,
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer1,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
NVIC_Timer1_Init(ENABLE,Priority_0); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
2.3 定时器中断处理函数中,进行IO反转,当前采用的IO口为P36
//========================================================================
// 函数: Timer1_ISR_Handler
// 描述: Timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer1_ISR_Handler (void) interrupt TMR1_VECTOR //进中断时已经清除标志
{
// TODO: 在此处添加用户代码
T1_Load(g_u16Pwm4[s_u1Index]);
if(s_u1Index){
P36 = 1;
} else {
P36 = 0;
}
s_u1Index = ~s_u1Index;
}
2.4 修改占空比或者频率
因定时器采用向上计数,因此设置时,需要从上向下来实现
// [0] = 高电平时间
// [1] = 低电平时间
// 每个数字代表0.04us,
s_u16Pwm4[0] = (65535-(duty*14));
s_u16Pwm4[1] = (65535-14000+duty*14);
g_u16Pwm4[0] = s_u16Pwm4[0];
g_u16Pwm4[1] = s_u16Pwm4[1];
三、效果
最快测试过20Khz,当前只需要2Khz,满足要求。