现在学了定时模式 又开始生产网络垃圾了
主要看你拿哪个定时器 高级定时器和通用计算频率的公式不一样(看手册 )
高级定时器
(fCK_CNT)等于fCK_PSC/( PSCR[15:0]+1) |
通用定时器
fCK_CNT等于fCK_PSC/2(PSC[3:0]) |
根据时钟树 STM8S一般不外接晶振 使用内部HSI RS16Mhz 经过预分频器默认8分频 只剩下2Mhz
如需要超频可以修改 时钟分频寄存器(CLK_CKDIVR) 改变预分频系数
配置好时钟部分 就可以计算计数器的频率了
例:系统时钟不超频默认2Mhz PSCR分频因子可以配置为1 时钟2分频
fck_CNT = 2Mhz/2^1 = 1Mhz 这样计数器频率就成了1Mhz 周期为1us
如需定时1秒 ARR就可以设置为1000次 这样一个溢出周期就变成1ms 然后在中断中再用一个变量计数1000次就实现了1s定时
/* 基本定时模式 */
// TIM2_PSCR = 0X01;//设置分频因子为1 系统默认时钟为2Mhz,PSC_CNT = PSC_CK/2^PSCE次方
// TIM2_CNTRH = 0X00;
// TIM2_CNTRH = 0X00;//计数器清零
// TIM2_CR1 |= (1<<2 | 1<<0); //控制寄存器1
// TIM2_IER |= (1<<0);//中断使能寄存器 使能中断
// TIM2_ARRH = 0X03;
// TIM2_ARRL = 0XE8;//计数器F为1MHZ F = 1/T T = 1/F 一个周期为1us 设置ARR为1000 就是一毫秒出现一次更新中断
TIM2_CR1 使能计数器 (具体看手册)
IER为使能更新中断
#pragma vector = 15
__interrupt void TIM2_IRQHandle(void)
{
if(TIM2_SR1_UIF == 1)
{
TIM2_SR1_UIF = 0;
conunt++;
if(conunt == 1000)
{
conunt=0;
LED1 = ~LED1;
}
}
}
TIM2_SR1_UIF为中断更新溢出标志位 由硬件置1 软件清零
输出比较 (输出PWM波)
为了兼容有些所需频率较高的场景 一般会重新设置预分频器 (CLK_CKDIVR) 改为16Mhz(图一可见详细)
PSCR预分频器设置为1分频 计数器时钟为16Mhz
然后设置输出比较模式 一下均使用通用定时器TIM2 CH1单通道输出
配置输出模式 选择PWM1模式 也就是说计数器CNT的值<CCR时为有效电平 >时为无效电平 (向上计数时)这一位由TIMx_CCMRa来配置 (a的取值为1~3) 还得使能输出比较预装载OC1PE
接下来配置有效电平 由TIMx_CCERb来配置(b的取值为1~2)CCIP(位1) 模式为高电平0有效
使能输出CC1E 为1才能输出
接下来是pwm的核心,频率以及占空比的设置:
/* Set the Autoreload value */
TIM2_ARRH = 0x00;
TIM2_ARRL = 0x8a;
/*TIM2 Frequency=16M/138=115k*/
TIM2_CCR1H = 0x00; //设置PWM输出占空比为40%
TIM2_CCR1L = 0X37;
下面说一下计算的方法:
由时钟的配置可知 时钟为16M,自动重装载的值为0x008a=138;
所以 f=16M/138=115k;
占空比计算:0x0037=55;占空比=55/138=40%
最后使能一下计数器 TIMx_CR1 第0位
// CLK_CKDIVR= 0x00; //内部16M时钟不分频
// TIM2_PSCR = 0x01; //定时器2预分频系数为1
// TIM2_CR1 = 0x01; //内部计数器使能;
// TIM2_ARRH = 0x00;//0140,320分频,16M/320=50K,实测49.75K
// TIM2_ARRL = 0x8a;//自动装载寄存器低位;实测013e正好为50.0K
// /*PWM通道1设置*/
// TIM2_CCER1 |= 0x01; //开启OC1信号输出脚
// TIM2_CCMR1 = 0x60; //PWM1模式
// TIM2_CCR1H = 0x00; //占空比高位
// TIM2_CCR1L = 0x37; //占空比低位
// TIM2_CCMR1 |= 0x08; //输出比较1预装载使能
// /*PWM通道2设置*/
// TIM2_CCER1 |= 0x10; //开启OC2信号输出脚
// TIM2_CCMR2 = 0x60; //PWM1模式
// TIM2_CCR2H = 0x00; //占空比高位
// TIM2_CCR2L = 0x37; //占空比低位
// TIM2_CCMR2 |= 0x08; //输出比较2预装载使能
// /*PWM通道3设置*/
// TIM2_CCER2 |= 0x01; //开启OC3信号输出脚
// TIM2_CCMR3 = 0x60; //PWM1模式
// TIM2_CCR3H = 0x00; //占空比高位
// TIM2_CCR3L = 0x37; //占空比低位
// TIM2_CCMR3 |= 0x08; //输出比较3预装载使能
// TIM2_CR1 |= 0x01;
#代码样例
有关引脚复用参考这位大哥博客 (一开始没注意这回事一度自我怀疑)