使用STC8的Timer控制IO輸出
STC8系列單片機具有多個定時器,可以用于精確控制IO口的輸出狀態。以下是使用Timer0和Timer1控制IO輸出的方法。
初始化Timer0
配置Timer0為16位自動重裝模式,用于周期性控制IO輸出:
/************************ 定時器配置 ****************************/
void Timer_config(void)
{TIM_InitTypeDef TIM_InitStructure; //結構定義//定時器0做16位自動重裝, 中斷頻率為1000HZTIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMaskTIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定時鐘源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext//如果配置ENABLE,則P3.5端口會同步輸出時鐘脈沖TIM_InitStructure.TIM_ClkOut = DISABLE; //是否輸出高速脈沖, ENABLE或DISABLE// 1秒鐘要調用1000次定時器中斷函數,每1/1000秒,1ms,調用1次定時器中斷函數TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 1000UL); //初值 ---------------------- 設置輸出頻率1000Hz, 1ms// 頻率不能太低:>= 367// 頻率不能太高:<= 1000000(1MHz) 否則不準確// 65536 - (24000 000 / 1000) = 65536 - 24000 = 41536 (TIM_Value)// 0 |----------------------------------------| 41536 |---------------| 65535// +++++++++++++++ 每溢出一次,執行一次中斷函數TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后啟動定時器, ENABLE或DISABLETimer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4NVIC_Timer0_Init(ENABLE,Priority_0); //中斷使能, ENABLE/DISABLE; 優先級(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
Timer0中斷服務程序
在中斷中翻轉IO口狀態:
我是寫了一個函數的聲明
extern void timer0_call();
我調用了這個函數
timer0_call();
在原本的庫文件中寫的,函數中調用了函數,具體實現的邏輯都在main.c文件中實現
extern void timer0_call(); // 誰要使用,誰要定義此回調函數void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR //進中斷時已經清除標志
{// TODO: 在此處添加用戶代碼timer0_call();//我添加的代碼
}
使用Timer1的PWM功能
STC8的Timer1可以產生PWM信號控制IO輸出
直接IO控制
通過定時器中斷直接控制多個IO口:
// 定時器0中斷回調函數
void timer0_call() {u8 i = 0;if(COM1.RX_Cnt > 0) {for(i=0; i<COM1.RX_Cnt; i++) {// RX1_Buffer[i]存的是接收的數據// TODO: 做具體的邏輯TX1_write2buff(RX1_Buffer[i]);// 寫一個byte}}COM1.RX_Cnt = 0;
}
案例代碼
main.c文件
#include "GPIO.h"
#include "Timer.h"
#include "NVIC.h"
#include "UART.h"
#include "Switch.h"// 配置timer控制UART接收:在Timer中斷函數中接收并處理UART消息void GPIO_config(void) {GPIO_InitTypeDef GPIO_InitStructure; //結構定義// P30 P31GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO,GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的輸入或輸出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化
}/************************ 定時器配置 ****************************/
void Timer_config(void)
{TIM_InitTypeDef TIM_InitStructure; //結構定義//定時器0做16位自動重裝, 中斷頻率為1000HZTIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMaskTIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定時鐘源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext//如果配置ENABLE,則P3.5端口會同步輸出時鐘脈沖TIM_InitStructure.TIM_ClkOut = DISABLE; //是否輸出高速脈沖, ENABLE或DISABLE// 1秒鐘要調用1000次定時器中斷函數,每1/1000秒,1ms,調用1次定時器中斷函數TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 1000UL); //初值 ---------------------- 設置輸出頻率1000Hz, 1ms// 頻率不能太低:>= 367// 頻率不能太高:<= 1000000(1MHz) 否則不準確// 65536 - (24000 000 / 1000) = 65536 - 24000 = 41536 (TIM_Value)// 0 |----------------------------------------| 41536 |---------------| 65535// +++++++++++++++ 每溢出一次,執行一次中斷函數TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后啟動定時器, ENABLE或DISABLETimer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4NVIC_Timer0_Init(ENABLE,Priority_0); //中斷使能, ENABLE/DISABLE; 優先級(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}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_BRTxCOMx_InitStructure.UART_BRT_Use = BRT_Timer1; //選擇波特率發生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable = ENABLE; //接收允許, ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1); //中斷使能, ENABLE/DISABLE; 優先級(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31); // 引腳選擇, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}// 定時器0中斷回調函數
void timer0_call() {u8 i = 0;if(COM1.RX_Cnt > 0) {for(i=0; i<COM1.RX_Cnt; i++) {// RX1_Buffer[i]存的是接收的數據// TODO: 做具體的邏輯TX1_write2buff(RX1_Buffer[i]);// 寫一個byte}}COM1.RX_Cnt = 0;
}void main() {// 配置GPIO_config();Timer_config();UART_config();// 全局中斷使能EA = 1;while (1) {}
}
庫函數:Timer_isr.c文件需要在Timer0_ISR_Handler 中添加需要中斷的接口或者給一個調用的函數
#include "Timer.h"// 函數聲明
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();//我添加的代碼
}
注意事項
- 時鐘頻率影響定時精度,需根據實際系統時鐘調整定時器初值
- 使用PWM功能時需注意IO口的復用功能配置
- 高精度定時需考慮中斷響應時間的補償
以上方法適用于STC8系列單片機的Timer控制IO輸出應用,可根據具體需求調整定時器配置和IO操作邏輯。