USART串口通讯函数实现 (基于寄存器)

环境

芯片:STM32F103ZET6

库:来自HAL的STM32F1XX.H

原理图

如图可知TX和RX两条线接到了PA9和PA10

  • Driver_USART1.h

    • #ifndef __DRIVER_USART1_H
      #define __DRIVER_USART1_H
      
      #include "stm32f1xx.h"
      
      /**
       * 初始化USART1  完成相关配置 能够调用下面收发数据的代码
       */
      void Driver_USART1_Init(void);
      
      /**
       * 发送一个字节
       * uint8_t ch: 需要发送的一个字节
       */
      void Driver_USART1_SendChar(uint8_t ch);
      
      /**
       * 接收一个字节
       * return: uint8_t 接收到的字节
       */
      uint8_t Driver_USART1_ReceiveChar(void);
      
      /**
       * 发送多个字节
       * uint8_t *str: 一个字符串
       * uint8_t len: 字符串长度
       */
      void Driver_USART1_SendString(uint8_t *str,uint8_t len);
      
      /**
       * 接收多个字节  ->  由于不能确定接收数据的长度 ->  推荐buff够大
       * 收到空闲位结束
       * uint8_t buff[]: 存接收到的数据
       * uint8_t * len: 实际接收数据的长度 -> 需要函数中赋值
       */
      void Driver_USART1_ReceiveString(uint8_t buff[],uint8_t * len);
      
      #endif
      
  •  Driver_USART1.c

    • #include "Driver_USART1.h"
      
      /**
       * 初始化USART1  完成相关配置 能够调用下面收发数据的代码
       */
      void Driver_USART1_Init(void)
      {
          /* 1. 打开USART1相关时钟 AFIO主要控制事件和外部中断 -> 片上外设的复用引脚有专门的位控制 */
          RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
          RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
          /* 2. 配置使用到的引脚模式  ->  PA9 TX 复用推挽输出 1011 ->  PA10 RX 浮空输入模式  0100 */
          GPIOA->CRH |= (GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9);
          GPIOA->CRH &= ~(GPIO_CRH_CNF9_0);
      
          GPIOA->CRH |= GPIO_CRH_CNF10_0;
          GPIOA->CRH &= ~(GPIO_CRH_CNF10_1 | GPIO_CRH_MODE10);
      
          /* 3. 配置USART1 */
          // 3.1 配置波特比率
          USART1->BRR = 0X0271;
          // 3.2 数据长度  8位
          USART1->CR1 &= ~(USART_CR1_M);
          // 3.3 校验位
          USART1->CR1 &= ~(USART_CR1_PCE);
          // 3.4 停止位
          USART1->CR2 &= ~(USART_CR2_STOP);
      
          // 3.5 打开使能开关
          // 3.5.1 发送开关
          USART1->CR1 |= USART_CR1_TE;
          // 3.5.2 接收开关
          USART1->CR1 |= USART_CR1_RE;
          // 3.5.3 总开关
          USART1->CR1 |= USART_CR1_UE;
      }
      
      /**
       * 发送一个字节
       * uint8_t ch: 需要发送的一个字节
       */
      void Driver_USART1_SendChar(uint8_t ch)
      {
          // 往DR寄存器直接写 -> 发送数据
          // 需要等待上一个字节发送完成之后  ->  才能发送下一个字节
          // SR_TXE   如果数据正在发 ->  0
          //          如果数据发生完成 -> 1
          while ((USART1->SR & USART_SR_TXE) == 0)
              ;
      
          USART1->DR = ch;
      }
      
      /**
       * 接收一个字节
       * return: uint8_t 接收到的字节
       */
      uint8_t Driver_USART1_ReceiveChar(void)
      {
          // 接收数据也需要挂起 -> 等待有数据传入
          // SR_RXNE : 有数据进来 -> 1
          //           读取一次之后 -> 0
          while ((USART1->SR & USART_SR_RXNE) == 0)
              ;
          return USART1->DR;
      }
      
      /**
       * 发送多个字节
       * uint8_t *str: 一个字符串
       * uint8_t len: 字符串长度
       */
      void Driver_USART1_SendString(uint8_t *str, uint8_t len)
      {
          for (uint8_t i = 0; i < len; i++)
          {
              Driver_USART1_SendChar(str[i]);
          }
      }
      
      /**
       * 接收多个字节  ->  由于不能确定接收数据的长度 ->  推荐buff够大
       * 收到空闲位结束
       * uint8_t buff[]: 存接收到的数据
       * uint8_t * len: 实际接收数据的长度 -> 需要函数中赋值
       */
      void Driver_USART1_ReceiveString(uint8_t buff[], uint8_t *len)
      {
          uint8_t i = 0;
          while (1)
          {
              // 1. 收到数据  存缓存
              if (USART1->SR & USART_SR_RXNE)
              {
                  buff[i] = USART1->DR;
                  i++;
              }
      
              // 2. 收到空闲 停止
              if (USART1->SR & USART_SR_IDLE)
              {
                  
                  *len = i;
                  break;
              }
      
          }
      }
      
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值