3.填写数据到UART发送缓冲区 。并启动发送中断,中断处理函数发送完毕后,自动关闭发送中断 .
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen) {uint16_t i;for (i = 0; i < _usLen; i++){/* 如果发送缓冲区已经满了,则等待缓冲区空 */while (1){__IO uint16_t usCount;DISABLE_INT();usCount = _pUart->usTxCount;ENABLE_INT();if (usCount < _pUart->usTxBufSize){break;}else if(usCount == _pUart->usTxBufSize)/* 数据已填满缓冲区 */{if((_pUart->uart->CR1 & USART_CR1_TXEIE) == 0){SET_BIT(_pUart->uart->CR1, USART_CR1_TXEIE);}}}/* 将新数据填入发送缓冲区 */_pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf[i];DISABLE_INT();if (++_pUart->usTxWrite >= _pUart->usTxBufSize){_pUart->usTxWrite = 0;}_pUart->usTxCount++;ENABLE_INT();}SET_BIT(_pUart->uart->CR1, USART_CR1_TXEIE); /* 使能发送中断(缓冲区空) */ } 123456789101112131415161718192021222324252627282930313233344.向串口发送一组数据 。数据放到发送缓冲区后立即返回,由中断服务程序在后台完成发送
void comSendBuf(COM_PORT_E _ucPort, uint8_t *_ucaBuf, uint16_t _usLen) {UART_T *pUart;pUart = ComToUart(_ucPort);if (pUart == 0){return;}if (pUart->!= 0){pUart->SendBefor(); /* 如果是RS485通信,可以在这个函数中将RS485设置为发送模式 */}UartSend(pUart, _ucaBuf, _usLen); }123456789101112131415向串口发送1个字节 。数据放到发送缓冲区后立即返回,由中断服务程序在后台完成发送
void comSendChar(COM_PORT_E _ucPort, uint8_t _ucByte) {comSendBuf(_ucPort, &_ucByte, 1); } 123456函数comSendChar是发送一个字节,通过调用函数comSendBuf实现,而函数comSendBuf又是通过调用函数UartSend实现,这个函数是重点 。
5.将COM端口号转换为UART指针UART_T *ComToUart(COM_PORT_E _ucPort) {if (_ucPort == COM1){#if UART1_FIFO_EN == 1return &g_tUart1;#elsereturn 0;#endif}else{Error_Handler(__FILE__, __LINE__);return 0;} }12345678910111213141516176.从串口接收缓冲区读取1字节数据static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte) {uint16_t usCount;/* usRxWrite 变量在中断函数中被改写,主程序读取该变量时,必须进行临界区保护 */DISABLE_INT();usCount = _pUart->usRxCount;ENABLE_INT();/* 如果读和写索引相同,则返回0 *///if (_pUart->usRxRead == usRxWrite)if (usCount == 0) /* 已经没有数据 */{return 0;}else{*_pByte = _pUart->pRxBuf[_pUart->usRxRead]; /* 从串口接收FIFO取1个数据 *//* 改写FIFO读索引 */DISABLE_INT();if (++_pUart->usRxRead >= _pUart->usRxBufSize){_pUart->usRxRead = 0;}_pUart->usRxCount--;ENABLE_INT();return 1;} } 1234567891011121314151617181920212223242526272829从接收缓冲区读取1字节,非阻塞 。无论有无数据均立即返回 。
uint8_t comGetChar(COM_PORT_E _ucPort, uint8_t *_pByte) { UART_T *pUart;pUart = ComToUart(_ucPort);if (pUart == 0) {return 0;}return UartGetChar(pUart, _pByte); }123456789101112接收数据的调用顺序是:comGetChar–》UartGetChar
7.判断发送缓冲区是否为空uint8_t UartTxEmpty(COM_PORT_E _ucPort){UART_T *pUart;uint8_t Sending;pUart = ComToUart(_ucPort);if (pUart == 0){return 0;}Sending = pUart->Sending;if (Sending != 0){return 0;}return 1;}12345678910111213141516171819208.清零串口接收缓冲区void comClearRxFifo(COM_PORT_E _ucPort){ UART_T *pUart; pUart = ComToUart(_ucPort); if (pUart == 0) {return; } pUart->usRxWrite = 0; pUart->usRxRead = 0; pUart->usRxCount = 0;}1234567891011129.清零串口发送缓冲区void comClearTxFifo(COM_PORT_E _ucPort){ UART_T *pUart; pUart = ComToUart(_ucPort); if (pUart == 0) {return; } pUart->usTxWrite = 0; pUart->usTxRead = 0; pUart->usTxCount = 0;}123456789101112131410.输入输出的重定向int fputc(int ch, FILE *f){#if 1 /* 将需要printf的字符通过串口中断FIFO发送出去,printf函数会立即返回 */ comSendChar(COM1, ch); return ch;#else /* 采用阻塞方式发送每个字符,等待数据发送完毕 */ /* 写一个字节到USART1 */ USART1->DR = ch; /* 等待发送结束 */ while((USART1->SR & USART_SR_TC) == 0) {} return ch;#endif}int fgetc(FILE *f){#if 1 /* 从串口接收FIFO中取1个数据, 只有取到数据才返回 */ uint8_t ucData; while(comGetChar(COM1, &ucData) == 0); return ucData;#else /* 等待接收到数据 */ while((USART1->SR & USART_SR_RXNE) == 0) {} return (int)USART1->DR;#endif}123456789101112131415161718192021222324252627282911.应用层初始化://FIFO串口初始化UartVarInit(void);//串口参数配置void bsp_SetUartParam(USART_TypeDef *Instance,uint32_t BaudRate, uint32_t Parity, uint32_t Mode){ UART_HandleTypeDef UartHandle;/*##-1- 配置串口硬件参数 ######################################*/ /* 异步串口模式 (UART Mode) */ /* 配置如下:- 字长= 8 位- 停止位= 1 个停止位- 校验= 参数Parity- 波特率= 参数BaudRate- 硬件流控制关闭 (RTS and CTS signals) */ UartHandle.Instance= Instance; UartHandle.Init.BaudRate= BaudRate; UartHandle.Init.wordLength = UART_WORDLENGTH_8B; UartHandle.Init.StopBits= UART_STOPBITS_1; UartHandle.Init.Parity= Parity; UartHandle.Init.HwFlowCtl= UART_HWCONTROL_NONE; UartHandle.Init.Mode= Mode; UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&UartHandle) != HAL_OK) {Error_Handler(__FILE__, __LINE__); }}//对应的串口波特率配置void comSetBaud(COM_PORT_E _ucPort, uint32_t _BaudRate){ USART_TypeDef* USARTx; USARTx = ComToUSARTx(_ucPort); if (USARTx == 0) {return; } bsp_SetUartParam(USARTx,_BaudRate, UART_PARITY_NONE, UART_MODE_TX_RX);}//硬件初始化void InitHardUart(void){GPIO 复用.... /* 配置NVIC the NVIC for UART */HAL_NVIC_SetPriority(USART1_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART1_IRQn);/* 配置波特率、奇偶校验 */ bsp_SetUartParam(USART1,UART1_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX); CLEAR_BIT(USART1->SR, USART_SR_TC);/* 清除TC发送完成标志 */CLEAR_BIT(USART1->SR, USART_SR_RXNE); /* 清除RXNE接收标志 */ // USART_CR1_PEIE | USART_CR1_RXNEIE SET_BIT(USART1->CR1, USART_CR1_RXNEIE); /* 使能PE. RX接受中断 */}在主循环中comGetChar(COM1, &read);//获取一个字节数据comSendBuf(COM1, (uint8_t *)buf, strlen(buf));//发送数据12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
推荐阅读
- 手机wifi经常断网、掉线,接收消息延迟?原来是这个开关没打开
- 马云|洪金宝对马云的评价,实在是太直白了!
- 陈钰琪|对不起!带着《香蜜》的滤镜,我也接受不了陈钰琪跟王鹤棣演CP
- 幼儿园家长寄语对老师的话?幼儿园家长对老师寄语大全_2
- 科幻|国产科幻游戏《戴森球计划》大更新预告:对阵浩瀚星河舰队
- 寺庙对联集萃 寺庙对联
- 差价最高9000元,华为Mate 50系列怎么选?配置详细对比一文看懂
- |领导看到你在努力工作,对你会有所赏识
- 成吉思汗西征死了多少士兵?成吉思汗的部队
- 小米12对比小米mix4?小米12比小米mix4更香
