完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
`在前面的章节有跟大家一起实现基于RT-Thread 的按键控制功能,在本章节中将与大家一起来通过 RT-Thread提供的 I/O 设备管理接口来访问串口硬件。 首先进行相关硬件初始化,在rt_hw_board_init()函数里面增加SysInit()初始化函数,将需要使用的Systick、GPIO和UART先进行初始化。 void rt_hw_board_init() { #if 0 /* System Clock Update */ SystemCoreClockUpdate(); /* System Tick Configuration */ _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); #endif SysInit(); //添加硬件相关的初始化 /* Call components board initial (use INIT_BOARD_EXPORT()) */ #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif #if defined (RT_USING_USER_MAIN) && defined (RT_USING_HEAP) rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get()); #endif } void SysTick_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); rt_tick_increase(); /* leave interrupt */ rt_interrupt_leave(); } 01 Systick初始化 void SysTickInit(void) { SysTick_Config(SystemCoreClock/RT_TICK_PER_SECOND); } 02 GPIO初始化 void LedGpioInit(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1 ; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); } 03 UART初始化 UART1 用于FinSH中,在rt_hw_console_getchar使用查询方式实现,同时输出相关调试信息所以UART1 不需要开中断,UART2 用于测试串口收发,开启接收中断和接收空闲中断,开启接收空闲中断后则可以接收任意不定长度数据。 void uartInit(void) { GPIO_InitTypeDef GPIO_InitStructure; UART_InitTypeDef UART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //UART1 Initial RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); UART_InitStructure.UART_BaudRate = UART1_BAUD; UART_InitStructure.UART_WordLength = UART_WordLength_8b; UART_InitStructure.UART_StopBits = UART_StopBits_1; UART_InitStructure.UART_Parity = UART_Parity_No; UART_InitStructure.UART_Mode = UART_Mode_Rx |UART_Mode_Tx; UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None; UART_Init(UART1, &UART_InitStructure);//初始化串口1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; //TX GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ; //RX GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); UART_ClearITPendingBit(UART1, UART_ISR_TXC);//清发送完成标志位 UART_Cmd(UART1, ENABLE);//使能串口1 //UART2 Initial RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART2, ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); UART_InitStructure.UART_BaudRate = UART2_BAUD; UART_InitStructure.UART_WordLength = UART_WordLength_8b; UART_InitStructure.UART_StopBits = UART_StopBits_1; UART_InitStructure.UART_Parity = UART_Parity_No; UART_InitStructure.UART_Mode = UART_Mode_Rx |UART_Mode_Tx; UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None; UART_Init(UART2, &UART_InitStructure);//初始化串口2 //串口2中断初始化 NVIC_InitStructure.NVIC_IRQChannel = UART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 UART_ClearITPendingBit(UART2, UART_IER_RXIDLE); UART_ITConfig(UART2, UART_IER_RX, ENABLE); UART_ITConfig(UART2, UART_IER_RXIDLE, ENABLE); //添加串口空闲中断使能 UART_Cmd(UART2, ENABLE);//使能串口2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ; //TX GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; //RX GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); UART_ClearITPendingBit(UART1, UART_ISR_TXC); } 注 对于串口接收不定长度数据,串口IDLE中断就比较适用,IDLE中断就是串口收完一帧数据后发生中断。比如一帧数据有8个byte,当8个byte接收结束后就产生IDLE中断。 IDLE中断在UART_IER 配置
IDLE的时间在UART_IDLR寄存器配置,复位默值是0x0C(例:串口配置115200bps UART_IDLR默认为0x0C,那IDLE时间 8.6us*12=103.2us ) 04 UART2中断处理 UART2开启了两个中断,一个接收中断把接收到的数据放入buff,一个接收空闲中断,当一包数据接收完后产生中断,释放一个信号量,供另外一个线程查询。 void UART2_IRQHandler(void) { uint8 RecCh; if( UART_GetFlagStatus(UART2,UART_ISR_RX)!=RESET ) // 串口接收中断 { RecCh = (uint8)UART_ReceiveData(UART2); g_UART2_RxBuf[g_UART2_RecPos++] = RecCh; UART_ClearITPendingBit(UART2, UART_ISR_RX); } if (UART_GetITStatus(UART2, UART_IER_RXIDLE) != RESET) //接收空闲中断 { g_UART2_RxBuf[g_UART2_RecPos] = ' |