参考文章
stm8单片机点亮LED中断定时串口读写功能测试笔记_stm8s207串口例程-CSDN博客
【STM8S】STM8S之定时器1的精确延时_stm8s003定时器1-CSDN博客
一、使用单片机必备的配置流程
main.c
1.配置系统时钟源
(1)选择时钟源(高频振荡器16MHZ、低频振荡器256K)一般选高
(2)时钟分频(16进制:0-15,表示0-65536任意分频)
SystemInit.c
#include "SystemInit.h"
#include "iostm8s003F3.h"
//系统时钟初始化
void SysClkInit(void){
CLK_SWR = 0xE1;//时钟源HSI
CLK_CKDIVR = 0x00;//时钟分频0
}
2.配置GPIO
(1)开启输入、输出对应IO
(2)选择输入输出模式(如推挽输出、浮空输入等)
(3)配置传输速度(不写则默认)
GpioOutput.c
#include "GpioOutput.h"
#include "iostm8s003F3.h"//寄存器配置的头文件
void GPIOInit(void){
PD_DDR |= (1<<3); //PD3
PD_CR1 |= (1<<3);//推挽输出
//PD_CR2//速度默认
}
3.定时器配置(延时中断、事件中断)
使能更新/捕获/比较模式
更新:事件达到溢出中断,触发并更新事件
比较:与软件设定值进行比较,达到触发中断
捕获:对外部事件每次达到要求捕获记录一次,计数器+1,直到达到设定的计数器值,触发中断
Timer.c
#include "Timer1.h"
#include "stm8s_tim1.h"//定时器1(最强大)
/************内部变量*****************/
static u32 gTimer1_Delay;//uint32_t
void TIMER1_Init(void)
{
/*时钟频率fCK_PSC/1分频为不分频,向上计数,周期值800, 重复计数器值为0
定时单位 = 定时器周期 / 时钟频率 800/16MHZ=0.00005s=50usz中断一次
低于50us的定时频率很容易影响代码的正常运行,因此STM8S的定时频率最快是50us*/
TIM1_TimeBaseInit(0,TIM1_COUNTERMODE_UP,800,0);
/*自动重载寄存器:可防止当更新事件(比如定时器溢出)发生时,造成计数值突变导致计时错误*/
TIM1_ARRPreloadConfig(ENABLE);
/*事件更新、比较、捕获中断的选择和使能*/
TIM1_ITConfig(TIM1_IT_UPDATE , ENABLE);
/*使能定时器*/
TIM1_Cmd(ENABLE);
}
二、延时函数配置
Timer.c(续)
void TIMER1_Decrement(void){
if(gTimer1_Delay!=0x00){
gTimer1_Delay--;
}
}
void TIMER1_Delay50US(u32 nTime){//50us
gTimer1_Delay = nTime;
while(gTimer1_Delay!=0);
}
void delay_ms( u32 nTime){//1ms
gTimer1_Delay = 20*nTime;
while(gTimer1_Delay != 0);
}
参考博主证明50u是单片机最低反应单位,低于50us会影响运行
三、中断函数
1.配置中断函数
将延时函数写进中断(则延时函数不需要开启重复计数模式)
(1)配置的GPIO内部中断的向量值11,根据stm8s_it.c中查到
(2)我这里选择的是更新事件中断去实现延时,因此根据图片上中断函数的注释,取决于我选择这个函数去配置中断
(3)延时函数写进中断
Timer.c(续)
#pragma vector=0xB
__interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void)
{
TIMER1_Decrement();
TIM1_ClearITPendingBit(TIM1_IT_UPDATE);
}
报错:Error[Li006]: duplicate definitions for "_interrupt_11";
解决方法:将中断模块中的这个调用函数注释掉
2.main.c中断部分
需要按照这个顺序写,头文件记得加上#include "intrinsics.h"