当前位置: 首页 > news >正文

STM32第十二节(中级篇):串口通信(第二节)——串口固件库函数以及串口发送和接收代码讲解

STM32第十二节(中级篇):串口通信(第二节)——串口固件库函数以及串口发送和接收代码讲解


串口固件库函数

代码片段

/** * @brief  USART Init Structure definition  */ typedef struct
{uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.The baud rate is computed using the following formula:- IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.This parameter can be a value of @ref USART_Word_Length */uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.This parameter can be a value of @ref USART_Stop_Bits */uint16_t USART_Parity;              /*!< Specifies the parity mode.This parameter can be a value of @ref USART_Parity@note When parity is enabled, the computed parity is insertedat the MSB position of the transmitted data (9th bit whenthe word length is set to 9 data bits; 8th bit when theword length is set to 8 data bits). */uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.This parameter can be a value of @ref USART_Mode */uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabledor disabled.This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;

        本节课的代码是基础的配置,在后续学习以及编写代码的时候有很大的作用在上述代码中,就是对于USART结构体的初始化,我们可以在野火的资料盘中找到,在stm32f10x_usart.h文件中可以找到。我们观察这段代码,逐行解释代码部分。

结构体参数解释

        uint32 _t USART BaudRate;        //波特率 BRR

        uint16_t USART WordLength;     //字长 CR_1/M

        uint16_t USART StopBits;           //停止位 CR_2/STOP

        uint16_t USART Parity;               //校验控制 CR_1 PCE、CR_1 PS 

        uint16_t USART Mode;               //模式选择CR_1 TE、CR_1 RE

        // 硬件流选择 CR_3 CTSE、CR_3 RTSE:

        uintl6_t USART HardwareFlowControl;

结构体参数配置

        字长可以设置为八位或九位,详细内容在上节课有细致讲到。

        每一段数据传输的时候都要有停止位(STOP),对于STOP来说,有四个可选择的时间段。

        如果有效验位的话,会分为奇效验和偶效验两种效验方式,当然也可以选择没有效验位。

        对于USART模式上的选择来说,有输入数据和输出数据的选择。

/** @defgroup USART_Word_Length * @{*/ #define USART_WordLength_8b                  ((uint16_t)0x0000)
#define USART_WordLength_9b                  ((uint16_t)0x1000)#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \((LENGTH) == USART_WordLength_9b))/** @defgroup USART_Stop_Bits * @{*/ #define USART_StopBits_1                     ((uint16_t)0x0000)
#define USART_StopBits_0_5                   ((uint16_t)0x1000)
#define USART_StopBits_2                     ((uint16_t)0x2000)
#define USART_StopBits_1_5                   ((uint16_t)0x3000)
#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \((STOPBITS) == USART_StopBits_0_5) || \((STOPBITS) == USART_StopBits_2) || \((STOPBITS) == USART_StopBits_1_5))/** @defgroup USART_Parity * @{*/ #define USART_Parity_No                      ((uint16_t)0x0000)
#define USART_Parity_Even                    ((uint16_t)0x0400)
#define USART_Parity_Odd                     ((uint16_t)0x0600) 
#define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \((PARITY) == USART_Parity_Even) || \((PARITY) == USART_Parity_Odd))/** @defgroup USART_Mode * @{*/ #define USART_Mode_Rx                        ((uint16_t)0x0004)
#define USART_Mode_Tx                        ((uint16_t)0x0008)
#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00))/** @defgroup USART_Hardware_Flow_Control * @{*/ 
#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\(((CONTROL) == USART_HardwareFlowControl_None) || \((CONTROL) == USART_HardwareFlowControl_RTS) || \((CONTROL) == USART_HardwareFlowControl_CTS) || \((CONTROL) == USART_HardwareFlowControl_RTS_CTS))

        以上就是有关结构体的参数构建,这个是最基本都要会的结构体,当然,还有同步时钟初始化结构体的相关构建。

同步时钟初始化结构体

代码展示

typedef struct
{uint16_t USART_Clock;   /*!< Specifies whether the USART clock is enabled or disabled.This parameter can be a value of @ref USART_Clock */uint16_t USART_CPOL;    /*!< Specifies the steady state value of the serial clock.This parameter can be a value of @ref USART_Clock_Polarity */uint16_t USART_CPHA;    /*!< Specifies the clock transition on which the bit capture is made.This parameter can be a value of @ref USART_Clock_Phase */uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitteddata bit (MSB) has to be output on the SCLK pin in synchronous mode.This parameter can be a value of @ref USART_Last_Bit */
} USART_ClockInitTypeDef;

结构体配置

/** @defgroup USART_Clock * @{*/ 
#define USART_Clock_Disable                  ((uint16_t)0x0000)
#define USART_Clock_Enable                   ((uint16_t)0x0800)
#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) || \((CLOCK) == USART_Clock_Enable))/** @defgroup USART_Clock_Polarity * @{*/#define USART_CPOL_Low                       ((uint16_t)0x0000)
#define USART_CPOL_High                      ((uint16_t)0x0400)
#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High))/** @defgroup USART_Clock_Phase* @{*/#define USART_CPHA_1Edge                     ((uint16_t)0x0000)
#define USART_CPHA_2Edge                     ((uint16_t)0x0200)
#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge))/** @defgroup USART_Last_Bit* @{*/#define USART_LastBit_Disable                ((uint16_t)0x0000)
#define USART_LastBit_Enable                 ((uint16_t)0x0100)
#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \((LASTBIT) == USART_LastBit_Enable))

串口编程常用函数

        我们在编程的时候常用的几个固件库函数一共有六个。接下来就仔细地为大家讲一下这六个函数。分别是串口初始化函数,中断配置函数,串口使能函数,数据发送函数,数据接收函数,中断状态位获取函数。

        串口初始化函数(void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);)

        中断配置函数(void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);)

        串口使能函数(void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);)

        数据发送函数(void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);)

        数据接收函数(void USART_SendBreak(USART_TypeDef* USARTx);)

        中断状态位获取函数(ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);)

        至此,全部理论部分就结束了,接下来就是代码的讲解:

串口发送和接收

硬件设计

                                                        TTL转USB电平(要有CH340驱动)

        今天所编写的第一个代码要求如下:

        单片机给电脑发送数据,电脑上位机把数据打印出来;

        电脑上位机给单片机发数据,单片机接收到数据之后立马发回给电脑,并打印出来。

编程流程

1.初始化串口需要用到的GPIO

        这些代码都放在了bsp_usart.h文件中,采用宏定义把我们所需要的usart串口所需要的GPIO引脚定义好:

// 串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler
2.初始化串口,USART_InitTypeDef,使能串口,中断配置(接收中断,中断优先级)

        首先,我们先定义结构体GPIO_InitTypeDef GPIO_InitStructure和USART_InitTypeDef USART_InitStructure;然后配置GPIO,首先打开APB2_GPIOA的时钟。然后就是串口外设的时钟,再接着就配置GPIO模式(老三套);配置USART Rx位浮空输入模式;就是我们刚刚讲的那几个串口结构体参数配置;

void USART_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);// 打开串口外设的时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;// 配置 针数据字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits = USART_StopBits_1;// 配置校验位USART_InitStructure.USART_Parity = USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 配置工作模式,收发一起USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(DEBUG_USARTx, &USART_InitStructure);// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);	// 使能串口USART_Cmd(DEBUG_USARTx, ENABLE);	    
}

        在电脑上位机向单片机传输数据时会有中断的产生,所以我们在这里还要配置中断函数,调节中断优先值,最后使能串口。

3.编写中断服务函数
static void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 *//* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure);
}
4.编写发送和接收函数

        那么我们可以试着编写一个固件库函数使得我们可以发送一个字节:

        首先我们确定参数输入,指定需要的串口,和一个字节的数据(只能是八位);接下来找到SendData函数,第一个形参为串口名,第二个形参为八位的数据;根据上节课的知识,应该是发送数据寄存器为空。我们进入循环,判断USART_GetFlagStatus(形参为串口名和USART_FLAG_TXE位)是否为空。

/*****************  发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

 小结

        创作不易,点个三连关注一下吧!!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Nginx与Tomcat的区别
  • 计算机网络部分基础知识
  • 安全无忧!Windows7全补丁旗舰版:集成所有补丁!
  • 【HBZ分享】MYSQL的联合索引 与 覆盖索引
  • 【二叉树进阶】--- 根据二叉树创建字符串
  • LabVIEW光纤水听器闭环系统
  • 数据库服务器运维最佳实践
  • record 关键字
  • 内核源码定制修改模块化技术总结
  • 线程的概念
  • 基于inotif的文件同步备份
  • 服务器是什么?怎么选择适合自己的服务器?
  • 设计模式 - 组合模式
  • 百问网全志系列开发板音频ALSA配置步骤详解
  • 找到财富杠杆然后再行动中精进 -《纳瓦尔宝典》读后感
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • CentOS7 安装JDK
  • Computed property XXX was assigned to but it has no setter
  • docker-consul
  • Github访问慢解决办法
  • node和express搭建代理服务器(源码)
  • October CMS - 快速入门 9 Images And Galleries
  • spring cloud gateway 源码解析(4)跨域问题处理
  • SSH 免密登录
  • Terraform入门 - 1. 安装Terraform
  • 复习Javascript专题(四):js中的深浅拷贝
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何合理的规划jvm性能调优
  • 深度学习中的信息论知识详解
  • 以太坊客户端Geth命令参数详解
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 白色的风信子
  • puppet连载22:define用法
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • # Redis 入门到精通(七)-- redis 删除策略
  • #Linux(帮助手册)
  • #知识分享#笔记#学习方法
  • ${factoryList }后面有空格不影响
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (4.10~4.16)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (六)c52学习之旅-独立按键
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (四)JPA - JQPL 实现增删改查
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (万字长文)Spring的核心知识尽揽其中
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)winform之ListView
  • (转载)hibernate缓存