Nuru_Banmian
Nuru_Banmian
Published on 2025-03-24 / 83 Visits
1
2

USART-串口通讯案例-轮询方式寄存器实现

USART.h

 #ifndef __USART_H
 #define __USART_H
 ​
 #include "stm32f10x.h"
 ​
 // 初始化
 void USART_Init(void);
 ​
 // 发送一个字符
 void USART_SendChar(uint8_t ch);
 ​
 // 接收一个字符
 uint8_t USART_ReceiveChar(void);
 ​
 ​
 ​
 #endif
 ​

USART.c

 #include "usart.h"

初始化

 void USART_Init(void)
 {
     // 1. 配置时钟
     RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
     RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
 ​
     // 2. GPIO工作模式
     //  PA9  TX(发送端):  复用推挽输出:CNF-10,MODE-11
     //  PA10 RX(接收端):  浮空输入:CNF-01,MODE-00
     GPIOA->CRH |= GPIO_CRH_MODE9;
     GPIOA->CRH |= GPIO_CRH_CNF9_1;
     GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
 ​
     GPIOA->CRH &= ~GPIO_CRH_MODE10;
     GPIOA->CRH &= ~GPIO_CRH_CNF10_1;
     GPIOA->CRH |= GPIO_CRH_CNF10_0;
     
     // 3. 串口设置
     // 3.1 波特率设置
     USART1->BRR = 0x271;
 ​
     // 3.2 收发使能及USART模块使能
     USART1->CR1 |= (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE)
 ​
     // 3.3 其他配置,设置数据帧格式
     USART1->CR1 &= ~USART_CR1_M;
     USART1->CR1 &= ~USART_CR1_PCE;
     USART1->CR1 &= ~USART_CR1_PS;
     USART1->CR2 &= ~USART_CR2_STOP;
 }

发送和接收一个字符

 // 发送一个字符
 void USART_SendChar(uint8_t ch)
 {
     // 判断SR里TXE是否为1
     while((USART1->SR & USART_SR_TXE) == 0) //TXE位为0时说明缓冲区未空,等待
     {}
 ​
     // 向DR写入新的要发送的数据
     USART1->DR = ch;
 }
 ​
 // 接收一个字符
 uint8_t USART_ReceiveChar(void)
 {
     while ((USART1->SR & USART_SR_RXNE) == 0)
     {
         // 增加一个判断空闲帧的条件
         if (USART1->SR & USART_SR_IDLE)
         {
             // 字符串接收完毕
             return 0;
         }
     }
     
     // 读取已经接收到的数据,等待接收下一个数据
     return USART1->DR;
 }

发送和接收字符串

 // 发送字符串
 void USART_SendString(uint8_t *str, uint16_t size)
 {
     for (uint8_t i = 0; i < size; i++)
     {
         USART_SendChar(str[i]);
     }
 }
 ​
 // 接收字符串
 ​
 void USART_ReceiveString(uint8_t buffer[], uint8_t *size)
 {
     // 定义一个变量,用来保存已经接收到的字符个数
     uint8_t i = 0;
 ​
     while ((USART1->SR & USART_SR_IDLE) == 0)
     {
         buffer[i] = USART_ReceiveChar();
         i++;
     }
     // 清除idle位,不清除会导致后面的while循环直接跳出,导致数据出错,idle的清除条件为读SR再读一次DR
     // USART->SR;       //前面一直有在读SR因此可以省略
     USART1->DR;
 ​
     * size = --i;
 }
 ​
 ​
 ​
 // void USART_ReceiveString(uint8_t buffer[], uint8_t *size)
 // {
 //     // 定义一个变量,用来保存已经接收到的字符个数
 //     uint8_t i = 0;
 ​
 //     // 外层循环不停接收下一个字符
 //     while (1)
 //     {
 //         // 内存循环,判断当前数据帧是否接收完毕
 //         while ((USART1->SR & USART_SR_RXNE) == 0)
 //         {
 //             // 额外增加一个条件,判断当前是否检测到空闲帧
 //             if (USART1->SR & USART_SR_IDLE)
 //             {
 //                 // 字符串接收完毕
 //                 *size = i;
 //                 return;
 //             }
 //         }
 //         // 把当前接收到的数据(字符)放入缓冲区
 //         buffer[i] = USART1->DR;
 //         i++;
 //     }
 // }

main.c

 #include "usart.h"
 #include "delay.h"
 #include <string.h>
 ​
 // 定义一个全局变量,接收缓冲区的size
 uint8_t buffer[100] = {0};
 uint8_t size = 0;
 ​
 int main(void)
 {
     //  初始化
     USART_Init();
 ​
     //发送单个字符
     USART_SendChar('a');
     USART_SendChar('t');
     USART_SendChar('\n');
 ​
     //发送字符串
     uint8_t * str = "hello world!\n";
     USART_SendString(str, strlen((char *)str));
 ​
     while (1)
     {
         // // 发送字符
         // USART_SendChar('x');
         // USART_SendChar('\n');
         // Delay_ms(1000);
 ​
         /*----------------------------------*/
         
         // 接收字符,再发回来
         // uint8_t ch = USART_ReceiveChar();
         // USART_SendChar(ch);
 ​
         /*----------------------------------*/
         // 接收字符串,再发回来
         USART_ReceiveString(buffer, &size);
         USART_SendString(buffer, size);
     }
 }




Comment