營銷型網(wǎng)站建設(shè)費用怎么這么大網(wǎng)絡(luò)營銷渠道
單片機(jī)GPIO中斷+定時器 實現(xiàn)模擬串口接收
- 解決思路
- 代碼示例
解決思路
串口波特率9600bps,每個bit約為1000000us/9600=104.16us; 定時器第一次定時時間設(shè)為52us即半個bit的時間,其目的是偏移半個bit時間,之后的每104us采樣并讀取1bit數(shù)據(jù)。使得采樣點搞好在每位數(shù)據(jù)脈寬的中間點。
代碼示例
- 串口波特率9600bps,每個bit約為1000000us/9600=104.16us;
- 定時器開始時定時時間設(shè)為52us,即半個bit的時間,并關(guān)閉定時器;
- GPIO設(shè)為中斷模式下降沿觸發(fā),測到第一個下降沿(即串口的S信號),定時器設(shè)定52us開啟定時,關(guān)閉GPIO中斷,并設(shè)置狀態(tài)為E_IO_UART_STATE_IDLE。
- 定時器觸發(fā)52us定時E_IO_UART_STATE_IDLE狀態(tài)改為E_IO_UART_STATE_START。定時器設(shè)置為104us,之后每觸發(fā)一次104us定時中斷讀取1bit串口數(shù)據(jù),直到8bits數(shù)據(jù)全部解析完成,重置為下次接收狀態(tài);
#if TCFG_SENSOR_CO_MODULE_EN
struct io_uart_t {uint8_t state;uint8_t index;uint8_t _data;uint8_t ready;uint8_t rxlen;uint8_t _recv[7];
};
static struct io_uart_t io_uart;
void timer1_init(void);
#endif#if TCFG_SENSOR_CO_MODULE_EN
enum {E_IO_UART_STATE_IDLE=0, // 空閑狀態(tài)E_IO_UART_STATE_START, // 開始接收數(shù)據(jù)E_IO_UART_STATE_END, // 數(shù)據(jù)接收完成
};#define TIMER1_TICK_HEAD 60 // 52us 104/2=52us 半個開始信號的時間
#define TIMER1_TICK_DATA 139 // 104us 1000000/9600=104.16us 一個數(shù)據(jù)位的時間
void timer1_init(void)
{SCCM1 |= RCC_SCCM1_TIMER1;TMOD |=Bit5_En ;TMOD &=Bit4_Dis;TH1=256-TIMER1_TICK_HEAD; TL1=256-TIMER1_TICK_HEAD; TR1=0; //定時器1使能運行EAL=1; //總中斷打開ET1=1; //定時器1中斷打開IRQ_Vic_Set(INT_TIMER1, pritrity_level_fourth); // 設(shè)置定時器優(yōu)先級最高// IRQ_Enable(IT_ALL);
}void Interrupt_GPIO0 (void) interrupt 20 //GPIO0中斷服務(wù)程序
{// P07=~P07;if(IO_GetIntState(GPIO_P0,GPIO_Pin_6)){// P07=~P07; // for test// TODO: 檢測到第一個下降沿:S信號,設(shè)置定時器初值52us,啟動定時器,關(guān)閉外部中斷TH1=256-TIMER1_TICK_HEAD; TL1=256-TIMER1_TICK_HEAD;TR1=1;io_uart.state = E_IO_UART_STATE_IDLE;IO_INT_Disable( GPIO_P0,GPIO_Pin_6);// IRQ_Disable(IT_GPIO0);IO_CleanIntState(GPIO_P0,GPIO_Pin_6);}P0_INT_REG = 0xff;
}/*中斷方式*/
void Interrupt_TIMRT1 (void) interrupt 3 //TIMRT1中斷服務(wù)程序
{ uint8_t checksum = 0;TF1 = 1; //清標(biāo)志// TIMER01_SetPeriod(TIMER1,TIMERMODE_VALUE,TIMER1_TICK);// P07=~P07; // for testif (io_uart.state == E_IO_UART_STATE_START) {P07=~P07; // FOR TESTio_uart._data = io_uart._data >> 1; // 數(shù)據(jù)右移一位if (P06 == 1) { io_uart._data |= 0x80; // 如讀取到的串口GPIO電平為高,高位位或運算}io_uart.index++;if (io_uart.index == 8) {io_uart.state = E_IO_UART_STATE_END;IO_INT_Enable( GPIO_P0,GPIO_Pin_6);// IRQ_Enable(IT_GPIO0);TR1=0;if (io_uart._data == 0xAA) {io_uart.rxlen = 0;memset(io_uart._recv, 0, sizeof(io_uart._recv));}io_uart._recv[io_uart.rxlen] = io_uart._data;io_uart.rxlen++;if (io_uart.rxlen == 7){checksum = (uint8_t)(io_uart._recv[1]+io_uart._recv[2]+io_uart._recv[3]+io_uart._recv[4]);if (checksum == io_uart._recv[5]) {// TODO: 和校驗正確// P07=~P07; // for test_this->sensor_co.covol = (uint16_t)(io_uart._recv[1]<<8 | io_uart._recv[2]);io_uart.ready = 1;}}}}if (io_uart.state == E_IO_UART_STATE_IDLE) {io_uart.state = E_IO_UART_STATE_START;io_uart.index = 0;io_uart._data = 0;TH1=256-TIMER1_TICK_DATA; TL1=256-TIMER1_TICK_DATA;}
}
#endifvoid main ()
{
#if TCFG_SENSOR_CO_MODULE_ENtimer1_init();RCC_Sccm1_ClockCmd(RCC_SCCM1_GPIO,ENABLE);IO_FUN_Config(GPIO_P0,GPIO_Pin_7,GPIO_FUNCTION_DF0); //配置引腳為GPIO功能 IO_OUT_Enable(GPIO_P0, GPIO_Pin_7);IO_PU_Enable(GPIO_P0, GPIO_Pin_7);// TOODO: 模擬串口接收/*只有P0和P1口可以配置為電平觸發(fā),其他端口只能配置為沿觸發(fā)*/IO_FUN_Config( GPIO_P0,GPIO_Pin_6,GPIO_FUNCTION_DF0); //配置引腳為GPIO功能IO_PU_Enable( GPIO_P0,GPIO_Pin_6);IO_INPUT_Enable(GPIO_P0,GPIO_Pin_6); //配置引腳為GPIO輸入模式IO_INT_Config( GPIO_P0,GPIO_Pin_6, falling); //需要外接接下拉電阻 IO_INT_Enable( GPIO_P0,GPIO_Pin_6);IRQ_Enable(IT_GPIO0);
#endifwhile(1)
{...
}}