我公司想做网站,了解宿迁建设网站,网站设计就业岗位分析,网站建设好处单片机GPIO中断定时器 软件串口通信 解决思路代码示例 解决思路
串口波特率9600bps,每个bit约为1000000us/9600104.16us#xff1b; 定时器第一次定时时间设为52us即半个bit的时间#xff0c;其目的是偏移半个bit时间#xff0c;之后的每104us采样并读取1bit数据。使得采样… 单片机GPIO中断定时器 软件串口通信 解决思路代码示例 解决思路
串口波特率9600bps,每个bit约为1000000us/9600104.16us 定时器第一次定时时间设为52us即半个bit的时间其目的是偏移半个bit时间之后的每104us采样并读取1bit数据。使得采样点搞好在每位数据脉宽的中间点。 代码示例
串口波特率9600bps,每个bit约为1000000us/9600104.16us定时器开始时定时时间设为52us即半个bit的时间并关闭定时器GPIO设为中断模式下降沿触发测到第一个下降沿即串口的S信号定时器设定52us开启定时关闭GPIO中断并设置状态为E_IO_UART_STATE_IDLE。定时器触发52us定时E_IO_UART_STATE_IDLE状态改为E_IO_UART_STATE_START。定时器设置为104us之后每触发一次104us定时中断读取1bit串口数据直到8bits数据全部解析完成重置为下次接收状态
#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_IDLE0, // 空闲状态E_IO_UART_STATE_START, // 开始接收数据E_IO_UART_STATE_END, // 数据接收完成
};#define TIMER1_TICK_HEAD 60 // 52us 104/252us 半个开始信号的时间
#define TIMER1_TICK_DATA 139 // 104us 1000000/9600104.16us 一个数据位的时间
void timer1_init(void)
{SCCM1 | RCC_SCCM1_TIMER1;TMOD |Bit5_En ;TMOD Bit4_Dis;TH1256-TIMER1_TICK_HEAD; TL1256-TIMER1_TICK_HEAD; TR10; //定时器1使能运行EAL1; //总中断打开ET11; //定时器1中断打开IRQ_Vic_Set(INT_TIMER1, pritrity_level_fourth); // 设置定时器优先级最高// IRQ_Enable(IT_ALL);
}void Interrupt_GPIO0 (void) interrupt 20 //GPIO0中断服务程序
{// P07~P07;if(IO_GetIntState(GPIO_P0,GPIO_Pin_6)){// P07~P07; // for test// TODO: 检测到第一个下降沿S信号设置定时器初值52us启动定时器关闭外部中断TH1256-TIMER1_TICK_HEAD; TL1256-TIMER1_TICK_HEAD;TR11;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中断服务程序
{ uint8_t checksum 0;TF1 1; //清标志// 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; // 数据右移一位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);TR10;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;TH1256-TIMER1_TICK_DATA; TL1256-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口可以配置为电平触发其他端口只能配置为沿触发*/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)
{...
}}