昨日快下班的时候抽空调了手头的三合一体验套装,目标明确,直奔TIM2而去。翻了翻STM8S Reference Manual,感觉TIM1不好对付,先从简单的TIM2下手。让LED循环亮1s灭1s吧,写了程序如下:
/*************************
**文件名称:main.c
**LED说明:LD2----PD3
** LD3----PD2
** LD4----PD0
**外部晶振:8MHz
**************************/
#include"stm8s105c_s.h"
void CLK_Init(void)
{
CLK_ECKR |=0x01; // 开启外部时钟
while(!(CLK_ECKR &0x02)); // 等待HSE准备就绪
CLK_CKDIVR &=0xF8; // CPU时钟不分频
CLK_SWR =OxB4; // 选择外部时钟
while(!(CLK_SWCR &0x08)); // 等待切换至HSE完成(STM8默认上电使用HSI)
CLK_SWCR |=0x02; // 使能HSI
}
void GPIO_Init(void)
{
PD_DDR |=0x0D;
PD_CR1 |=0x0D; // 配置PD0、PD2、PD3为推挽输出 PD_CR2 =0x00; // 摆率2MHz}
void TIM2_Init(void)
{
TIM2_PSCR =0x03; // TIM2的时钟频率=fCK_PSC/2^3,即8分频,得到1us时基 TIM2_ARRH =0x03;
TIM2_ARRL =0xE7; // TIM2_ARR初值设定为0x03e7=999,计数1000
TIM2_CR1 |=0x81; // 使能TIM2计数 TIM2_IER =0x01; // 允许TIM2溢出中断}
main()
{
_asm("sim"); // 禁止中断 CLK_Init();
GPIO_Init();
TIM2_Init();
_asm("rim"); // 开启中断 while(1);
}
/************************************************
**文件名称:stm8s_interrupt_verctor.c
**说明:以下内容为加入的部分,模板代码部分省略
*************************************************/
#include"stm8s105c_s.h"
// 代码省略
unsigned int count =0;
@far @interrupt void TIM2_1US(void)
{
count++;
TIM2_SR1 &=~(0x01); // 清除TIM2溢出中断标志位
if(count ==1000) // 1s时间到 {
count =0;
PD_ODR ^=0x0D; // LED翻转 }
return;
}
// TIM2在中断向量表中的定义
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext},/* reset */ {0x82, NonHandledInterrupt}, /* trap */ {0x82, NonHandledInterrupt}, /* irq0 */ {0x82, NonHandledInterrupt}, /* irq1 */ {0x82, NonHandledInterrupt},/* irq2 */ {0x82, NonHandledInterrupt},/* irq3 */ {0x82, NonHandledInterrupt}, /* irq4 */ {0x82, NonHandledInterrupt}, /* irq5 */ {0x82, NonHandledInterrupt}, /* irq6 */ {0x82, NonHandledInterrupt}, /* irq7 */ {0x82, NonHandledInterrupt}, /* irq8 */ {0x82, NonHandledInterrupt}, /* irq9 */ {0x82, NonHandledInterrupt},/* irq10 */ {0x82, NonHandledInterrupt}, /* irq11 */ {0x82, NonHandledInterrupt}, /* irq12 */ {0x82, TIM2_1US}, /* irq13 */ {0x82, NonHandledInterrupt},/* irq14 */ {0x82, NonHandledInterrupt}, /* irq15 */
// 以下内容省略
{0x82, NonHandledInterrupt}, /* irq29 */ // 手册中的32个中断向量,这里才29个,因为用的是STM8S105S4这款片子的原因,可能没那么多吧,cosmic真的很傻很强大。顺便了解了TIM2的中断级别也不错。
};
调试中遇到的问题一开始让我迷茫:LED亮4s灭4s,只好根据现象去改TIM2_ARR的值,心想我定1s你亮4s,那我就TIM2_ARR =0x00F9,计数250个总该可以吧。一试还真的可以。不过这让我更想不通了,8MHz外部晶振到CPU是不分频,而fMASTER到TIM2是8分频,也就是刚好产生了1us的时钟基准。晚上想起来是没配置主时钟的缘故,没配置就默认使用了HSI 2MHz的 RC振荡器,结果还是把它8分频,定时时间相差4倍就不稀奇了。到此,问题基本了结。上面的代码是完整的正确代码。不过有个BUG,那就是如果HSE故障,那可怜的STM8S就会傻傻地一直在哪儿等着,这个问题还没解决,初步想法是交给中断去处理。