完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
创建串口设备结构体 typedef struct { USART_TypeDef *uart;/*STM32内部串口设备指针*/ uint8_t *pTxBuf;/*发送缓冲区*/ uint8_t *pRxBuf;/*接收缓冲区*/ uint16_t usTxBufsize;/*发送缓冲区大小*/ uint16_t usRxBufsize;/*接收缓冲区大小*/ uint16_t usTxWrite;/*发送缓冲区写指针(FIFO机制)*/ uint16_t usTxRead;/*发送缓冲区读指针*/ uint16_t usTxCount;/*等待发送的数据个数*/ uint16_t usRxWrite;/*接收缓冲区写指针*/ uint16_t usRxRead;/*接收缓冲区读指针*/ uint16_t usRxCount;/*还未读取的新数据的个数*/ void (*SendBefor)(void);/*开始发送之前的回调函数*/ void (*SendOver)(void);/*发送完毕的回调函数指针*/ void (*ReciveNew)(void);/*串口收到数据的回调函数指针*/ }UART_T; 上述的接收缓冲区读写指针和发送缓冲区读写指针虽然是uint16_t的数据类型,但是在这里称之为指针,是因为其在队列中反应了数据读写时位置的变化。 static void UartVarInit(void) { g_tUart1.uart = USART1;/*串口设备*/ g_tUart1.pTxBuf = g_TxBuf1;/*发送缓冲区指针*/ g_tUart1.pRxBuf = g_RxBuf1;/*接收缓冲区指针*/ g_tUart1.usTxBufsize = UART1_TX_BUF_SIZE;/*发送缓冲区大小*/ g_tUart1.usRxBufsize = UART1_RX_BUF_SIZE;/*发送缓冲区大小*/ g_tUart1.usTxWrite = 0;/*发送缓冲区写指针初始化为0*/ g_tUart1.usTxRead = 0;/*发送缓冲区读指针初始化为0*/ g_tUart1.usRxWrite = 0;/*接收缓冲区写指针初始化为0*/ g_tUart1.usRxRead = 0;/*接收缓冲区读指针初始化为0*/ g_tUart1.usRxCount = 0;/*接收到的新数据个数*/ g_tUart1.usTxCount = 0;/*待发送的数据个数*/ g_tUart1.SendBefor = 0;/*发送数据前的回调函数*/ g_tUart1.SendOver = 0;/*发送完成的回调函数*/ g_tUart1.ReciveNew = 0;/*接收到新数据的回调函数*/ } 上述的初始化过程将读写指针初始化为0,表明最开始缓冲区中没有数据,也就是处于队列的最底部。 下面是初始化串口的硬件部分 static void InitHardUart(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; /*第一步:配置GPIO*/ /*使能串口1,PA,AFIO总线*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE); /*A9 USART1-Tx*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); /*A10 USART1-Rx*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); /*第2步:配置串口硬件参数*/ USART_InitStructure.USART_BaudRate = UART1_BAUD; USART_InitStructure.USART_WordLength = UART1_WORD_LENGTH; USART_InitStructure.USART_StopBits = UART1_STOP_BIT; USART_InitStructure.USART_Parity = UART1_PARITY; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; USART_ClockInit(USART1, &USART_ClockInitStructure); USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /*使能接收中断*/ /*不能在此处打开发送中断*/ USART_Cmd(USART1, ENABLE); /*小缺陷:串口配置好,如果直接send,则第一个字节发送不出去*/ USART_ClearFlag(USART1, USART_FLAG_TC);/*清发送完成标志,可以解决第一个字节无法正确发送的问题*/ } 上述过程是程序化步骤,没有思维难点,接下来配置串口中断 static void ConfigUartNVIC(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 在发送数据的时候,采用UartSend();这个函数进行发送 具体的代码如下所示: 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; } } _pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf; DISABLE_INT(); if (++_pUart->usTxWrite >= _pUart->usTxBufSize) { _pUart->usTxWrite = 0; } _pUart->usTxCount++;/*等待发送的数据个数*/ ENABLE_INT(); } USART_ITConfig(_pUart->uart, USART_IT_TXE, ENABLE);/*使能发送中断*/ } if(usCount < _pUart->usTxBufSize) { break; } 通过上述的这句话保证每次写入缓冲区时都能保证等待发送的个数都小于缓冲区本身的大小,当等待发送的数据个数超过缓冲区本身的大小时,程序将陷入死循环。 _pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf; 通过此条语句将要发送的数据送入缓冲区。 if (++_pUart->usTxWrite >= _pUart->usTxBufSize) { _pUart->usTxWrite = 0; } 上述语句即表示如果当前的写指针已经移动到FIFO的顶端时,对指针进行复位。 同时在将要发送的数据存储到缓冲区之后,就可以通过触发中断发送数据 具体的发送中断的函数如下所示: if (USART_GetITStatus(_pUart->uart, USART_IT_TXE) != RESET) { if(_pUart->usTxCount == 0) { USART_ITConfig(_pUart->uart, USART_IT_TXE, DISABLE);/*发送缓冲区的数据已经取完 时,禁止发送缓冲区空中断*/ USART_ITConfig(_pUart->uart, USART_IT_TC, ENABLE);/*使能数据发送完毕中断*/ } else { /*从发送FIFO取一个字节写入发送数据寄存器*/ USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]);/*此条语句通过调用库函数实现*/ if (++_pUart->usTxRead >= _pUart->usTxBufSize) { _pUart->usTxRead = 0; } _pUart->usTxCount--;/*每发送一个字节之后待发送数据个数减一*/ } } else if (USART_GetITStatus(_pUart->uart, USART_IT_TC) != RESET) { if (_pUart->usTxCount == 0) { /*如果发送的数据全部发送完毕时,禁止数据发送中断*/ USART_ITConfig(_pUart->uart, USART_IT_TC, DISABLE); } else { /*正常情况下,不会进入这个分支*/ USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]); /*进入此分支后,再次发送缓冲区的值*/ if (++_pUart->usTxRead >= _pUart->usTxBufSize) { _pUart->usTxRead = 0; } _pUart->usTxCount--; } } 上述代码完成了一个完整的数据发送的过程 下面阐述关于接收数据的过程,接收数据通过触发中断接收数据。 中断处理函数如下: if (USART_GetITStatus(_pUart->uart, USART_IT_RXNE) != RESET) { uint8_t ch; ch = USART_ReceiveData(_pUart->uart);/*通过库函数从接收移位寄存器中读取收到的数据*/ _pUart->pRxBuf[_pUart->usRxWrite] = ch;/*将数据存入接收缓冲区,每进入中断一次存取一次*/ if (++_pUart->usRxWrite >= _pUart->usRxBufSize) { _pUart->usRxWrite = 0; } if (_pUart->usRxCount < _pUart->usRxBufSize) { _pUart->usRxCount++; } } 在接收中断里面读取到接收移位寄存器的值并将值存储到FIFO中,然后通过UartGetChar()函数读取缓冲区的值。 static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte) { uint16_t usCount; DISABLE_INT(); usCount = _pUart->usRxCount; ENABLE_INT(); if(usCount == 0)/*沒有数据则返回*/ { return 0; } else { *_pByte = _pUart->pRxBuf[_pUart->usRxRead]; } } 通过上述函数*_pByte便是从缓冲区读出的值 最后,再指出一点,再发送数据的时候,将要发送的数据送入缓冲区时,用的是发送写指针,在中断中将发送缓冲区中的数据填入发送数据寄存器中用的是发送读指针。 在中断接收时用的是接收写指针,读取程序中用的是接收读指针。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1986 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1770 浏览 1 评论
1241 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
823 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1792 浏览 2 评论
2026浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
914浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
326浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
679浏览 3评论
666浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-3-2 00:26 , Processed in 0.781880 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191