STC8系列定时器(Timer)串口库函数使用指南

STC8系列单片机内置多个定时器和串口模块,官方库函数简化了配置流程。以下为关键函数及使用方法:

定时器头文件和依赖

1. Timer.c Timer.h Timer_Isr.c
2. NVIC.c NVIC.h

#include "Timer.h"
#include "NVIC.h"

实现初始化定时器和中断函数

需在中断控制寄存器中开启相应中断:

void	Timer_config(void)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义
	//定时器0做16位自动重装, 中断频率为1000HZ
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	//指定工作模式,   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     = 65536UL - (MAIN_Fosc / 1000UL);		//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;				//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);				//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
	NVIC_Timer0_Init(ENABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

中断使能配置

需在中断控制寄存器中开启相应中断:

EA = 1;                 //全局中断开关
ET0 = 1;                //定时器0中断允许
ES = 1;                 //串口中断允许

波特率计算方法

STC8系列波特率计算公式:
在这里插入图片描述
在这里插入图片描述

数据收发示例

收数据使用:

if(COM1.RX_TimeOut > 0) {
    //超时计数
    if(--COM1.RX_TimeOut == 0) {
        if(COM1.RX_Cnt > 0) {
            // 这里处理收到的数据,做具体的逻辑,可以调用自己的on_uart1_recv
            for(i=0; i<COM1.RX_Cnt; i++)	{
                // RX1_Buffer[i]存的是接收的每个字节,写出用 TX1_write2buff
            }
        }
        COM1.RX_Cnt = 0;
    }
}

// 不要处理的太快
delay_ms(10);

方法1
接收数据通过中断处理:修改Timer_Isr.c实现中断函数的调用,并在main.c中声明实现timer0_call函数

extern void timer0_call();//声明

//========================================================================
// 函数: Timer0_ISR_Handler
// 描述: Timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR		//进中断时已经清除标志
{
	// TODO: 在此处添加用户代码
	timer0_call();
}

然后在main.c中实现timer0_call:

void timer0_call(){
	// TODO: 在此处添加用户代码
}

方法2
直接在main.c中实现interrupt函数(记得删掉或注释掉Timer_Isr.c中对应的中断函数)

void Timer0_ISR (void) interrupt TMR0_VECTOR		//进中断时已经清除标志
{
	// TODO: 在此处添加用户代码
}

注意事项

  • 使用1T模式时需设置AUXR寄存器对应位
  • 12时钟模式下定时器初值计算与1T模式不同
  • 多串口系统需注意中断优先级配置

以上为STC8系列定时器与串口库函数的核心使用方法,具体参数需根据实际时钟频率和通信需求调整。

案例代码

1定时器控制电灯

#include    "GPIO.h"
#include	"Timer.h"
#include	"NVIC.h"

// 定时器配置:配置时间间隔  
void	Timer_config(void)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	//指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;		//指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
	// ENABLE,P35 同步输出脉冲
    TIM_InitStructure.TIM_ClkOut    = DISABLE;				//是否输出高速脉冲, ENABLE或DISABLE
	// 频率 1000hz ====> 时间间隔 1/1000 === 1000ms/1000 ===> 1ms ====> 1000us
    TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000UL);		//初值
    // 1s 时间间隔(周期)  周期的倒数就是频率   1/1s ==> 1 hz
    // TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1UL);
    // 用户设置定时器的频率 >= 367 hz
    TIM_InitStructure.TIM_Run       = ENABLE;				//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);				//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
	NVIC_Timer0_Init(ENABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}

int i = 0;

// 定时器中断处理逻辑函数的定义
// 在Timer_Isr.c中有被调用
void timer0_callback() { // 每隔1ms调用1次这个函数
    i++;
    if (i == 1000) { // 1000个1ms才进入1次    每隔1s,灯亮灭1次
        P53 = !P53;

        i = 0; // 重置
    }
}

void main() {
    EA = 1; // 使能中断开关

    P5_MODE_OUT_PP(GPIO_Pin_3); // 推挽输出

    Timer_config(); // 定时器配置

    while (1){
    }
    
}

2.定时器和pwm控制震动马达

#include "GPIO.h"
#include"Delay.h"
#include "UART.h"
#include "NVIC.h"
#include "Switch.h"
#include "STC8H_PWM.h"
#include	"Timer.h"

#define MOTOR  P01
int i = 0;


void GPIO_config(void) {

	GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
	GPIO_InitStructure.Pin  = GPIO_Pin_0 |GPIO_Pin_1;		//指定要初始化的IO,
	GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化

//推挽输出	P01
    P0_MODE_OUT_PP(GPIO_Pin_1);

    MOTOR = 0 ;
}
void UART_config(void) {
	// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
    COMx_InitDefine		COMx_InitStructure;					//结构定义
    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

  	NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}
#define PERIOD (MAIN_Fosc / 1000)

void	PWM_config(void)
{
	PWMx_InitDefine		PWMx_InitStructure;
	

	// 配置PWM6
	PWMx_InitStructure.PWM_Mode    		= CCMRn_PWM_MODE1;	//模式,		CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
	PWMx_InitStructure.PWM_Duty    		= 0.0 * PERIOD;	//PWM占空比时间, 0~Period
	PWMx_InitStructure.PWM_EnoSelect    = ENO6P;			//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
	PWM_Configuration(PWM6, &PWMx_InitStructure);			//初始化PWM,  PWMA,PWMB


	// 配置PWMB
	PWMx_InitStructure.PWM_Period   = PERIOD - 1;			//周期时间,   0~65535
	PWMx_InitStructure.PWM_DeadTime = 0;					//死区发生器设置, 0~255
	PWMx_InitStructure.PWM_MainOutEnable= ENABLE;			//主输出使能, ENABLE,DISABLE
	PWMx_InitStructure.PWM_CEN_Enable   = ENABLE;			//使能计数器, ENABLE,DISABLE
	PWM_Configuration(PWMB, &PWMx_InitStructure);			//初始化PWM通用寄存器,  PWMA,PWMB

	// 切换PWM通道
	PWM6_SW(PWM6_SW_P01);					//PWM6_SW_P21,PWM6_SW_P54,PWM6_SW_P01,PWM6_SW_P75
	// 初始化PWMB的中断
	NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}
void pwm_set_duty(char value){
  PWMx_Duty duty ;
  duty.PWM6_Duty = (value/100.0)*PERIOD;
  UpdatePwm(PWM6, &duty);

}
void	Timer_config(void)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义
	//定时器0做16位自动重装, 中断频率为1000HZ
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	//指定工作模式,   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     = 65536UL - (MAIN_Fosc / 1000UL);		//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;				//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);				//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
	NVIC_Timer0_Init(ENABLE,Priority_0);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
// 更新PWM占空比
void Update_pwm_duty(char value) { // 0 ~ 100
	PWMx_Duty duty;
	duty.PWM6_Duty = (value / 100.0) * PERIOD;
	UpdatePwm(PWM6, &duty);
}
void timer0_call(){
	// TODO: 在此处添加用户代码
   i++;
    if (i == 1) { // 1000个1ms才进入1次    每隔1s,震动1次
        //P01 = !P01;
        //可以加个循环修改占空比这个(100)
        Update_pwm_duty(100);

        i = 0; // 重置
    }
}

void main() {

    EAXSFR ();
		EA = 1;
    GPIO_config();
    UART_config();
    PWM_config();
    Timer_config();
    while (1){  
}
}
 
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐