完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32HAL库串口处理—中断事务
利用STM32串口接口接收和缓冲区机制(循环接口的原理)实现数据的准确接收和发送。为添加上层通信协议建立基础。为了方便使用,为函数接口标准 Arduino串口通信的接口函数 void begin(unsigned long baud);//初始化接口 void end(void);//关闭串口 int available(void);//获取缓存中可以读取的字节数 int peek(void);//从缓存中读取字节数据,但不删除该数据 int read(void);//从缓存中读取字节数据,并删除该数据 int availableWrite(void);//获取发送缓存还可以写入的字节数 void flush(void); //将发送缓存中的数据全部发送出去 void write(uint8_t c);//发送字节数据 代码实现 编写硬件层MSP支持代码 void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle-》Instance==USART1) { /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------》 USART1_TX PA10 ------》 USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle-》Instance==USART1) { /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------》 USART1_TX PA10 ------》 USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); } } 定义新的串口结构体 #define SERIAL_RX_BUFFER_SIZE 64 #define SERIAL_TX_BUFFER_SIZE 64 typedef struct { UART_HandleTypeDef handle; IRQn_Type irq; uint8_t recv; uint8_t rx_buffer[SERIAL_RX_BUFFER_SIZE]; uint8_t tx_buffer[SERIAL_TX_BUFFER_SIZE]; uint16_t rx_head; volatile uint16_t rx_tail; volatile uint16_t tx_head; uint16_t tx_tail; }Serial_t; 接口函数实现 实例化对象 Serial_t serial1; //UART_HandleTypeDef *huart1 = &(serial1.handle); Serial_t serial2; //实际未用到 serial_init() void serial_init(Serial_t *serial, uint32_t baud) { UART_HandleTypeDef *huart = &(serial-》handle); huart-》Init.BaudRate = baud; huart-》Init.WordLength = UART_WORDLENGTH_8B; huart-》Init.StopBits = UART_STOPBITS_1; huart-》Init.Parity = UART_PARITY_NONE; huart-》Init.Mode = UART_MODE_TX_RX; huart-》Init.HwFlowCtl = UART_HWCONTROL_NONE; huart-》Init.OverSampling = UART_OVERSAMPLING_16; if(serial == &serial1) { huart-》Instance = USART1; serial-》irq = USART1_IRQn; } else if(serial == &serial2) { huart-》Instance = USART2; serial-》irq = USART2_IRQn; } if(HAL_UART_Init(huart) != HAL_OK) { Error_Handler(); } //使能串口接收中断 HAL_UART_Receive_IT(huart, &(serial-》recv), 1); } serial_available() int serial_available(Serial_t *serial) { return (uint32_t)(SERIAL_RX_BUFFER_SIZE + serial-》rx_head - serial-》rx_tail) % SERIAL_RX_BUFFER_SIZE; } serial_peek() int serial_peek(Serial_t *serial) { if(serial-》rx_head == serial-》rx_tail) { return -1; } else { return serial-》rx_buffer[serial-》rx_tail]; } } serial_read() int serial_read(Serial_t *serial) { if(serial-》rx_head == serial-》rx_tail) { return -1; } else { uint8_t c = serial-》rx_buffer[serial-》rx_tail]; serial-》rx_tail = (uint16_t)(serial-》rx_tail + 1) % SERIAL_RX_BUFFER_SIZE; return c; } } availableWrite() int serial_availableForWrite(Serial_t *serial) { return (uint32_t)(SERIAL_TX_BUFFER_SIZE + serial-》tx_tail - serial-》tx_head - 1) % SERIAL_TX_BUFFER_SIZE; } serial_flush //只有在执行过serial_write()函数后才可使用该函数。 void serial_flush(Serial_t *serial) { while ((serial-》tx_head != serial-》tx_tail)) { // nop, the interrupt handler will free up space for us } // If we get here, nothing is queued anymore (DRIE is disabled) and // the hardware finished tranmission (TXC is set)。 } serial_write() void serial_write(Serial_t *serial, uint8_t c) { //HAL_UART_Transmit(&(serial-》handle),&c,1,1000); uint16_t i = (serial-》tx_head + 1) % SERIAL_TX_BUFFER_SIZE; while(i == serial-》tx_tail) //发送缓冲区满 { //什么也不做,等待缓冲区有空间 } serial-》tx_buffer[serial-》tx_head] = c; serial-》tx_head = i; if((HAL_UART_GetState(&(serial-》handle)) & HAL_UART_STATE_BUSY_TX) != HAL_UART_STATE_BUSY_TX) { /* Must disable interrupt to prevent handle lock contention */ HAL_NVIC_DisableIRQ(serial-》irq); HAL_UART_Transmit_IT(&(serial-》handle), &(serial-》tx_buffer[serial-》tx_tail]), 1); HAL_NVIC_EnableIRQ(serial-》irq); } } 中断服务函数 接收中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &(serial1.handle)) { uint16_t i = (uint32_t)(serial1.rx_head +1) % SERIAL_RX_BUFFER_SIZE; if(i != serial1.rx_tail) { serial1.rx_buffer[serial1.rx_head] = serial1.recv; serial1.rx_head = i; } /* 使能下次接收中断 */ HAL_UART_Receive_IT(huart, &(serial1.recv), 1); } } 发送中断回调函数 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &(serial1.handle)) { serial1.tx_tail = (serial1.tx_tail + 1) % SERIAL_TX_BUFFER_SIZE; if(serial1.tx_head == serial1.tx_tail) { return; } /* 发送完成后,再次使能中断发送直至发送缓冲区的数据全部发送完成 */ if (HAL_UART_Transmit_IT(huart, &serial1.tx_buffer[serial1.tx_tail], 1) != HAL_OK) { return; 中断函数 /** * @brief This function handles USART1 global interrupt. */ void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&(serial1.handle)); } 测试 int main(void) { /* 省略了初始化函数 */ while(1) { if(serial_available(&serial1)) { uint8_t c = serial_read(&serial1); serial_write(&serial1,c) } } } 利用该测试函数可以实现串口的回环接收。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1584 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1526 浏览 1 评论
958 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
672 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1567 浏览 2 评论
1852浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
622浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
508浏览 3评论
517浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
494浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-15 10:24 , Processed in 0.749515 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号