Coder
Published on 2025-04-09 / 21 Visits
0
0

单片机定时器模拟PWM输出-STC8H/G

一、由来

因单片机(STC8G1K08)选型问题,项目需要4路pwm输出,但实际只有3路,大写的尴尬!!!!

补充点题外话

STC8G1K08的PWM采用pca来实现,也比较坑

如果采用系统主频作为时钟源,只能做固定的分频

而采用定时器作为时钟,才能实现自定义频率,但是我的定时器用完了,漂亮!!!!

二、解决

该单片机有三个定时器,用一个定时器来做模拟pwm,因主频24M,基本能满足要求

1. 主要原理

  1. 首先定时器计时设置为高电平的时间

  2. 定时器中断触发,再次设置定时器计时为低电平时间

  3. 定时器中断触发,再次设置定时器计时为高电平时间,无线循环

  4. 在中断处理中,根据高电平还是低电平的时间,设置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,满足要求。


Comment