本文我们将了解STM32与外部设备通过串口通信的方式。

所谓串口通信,其实是一个类似于计算机网络的概念,它有物理层,比如规定用什么线通信,几伏特算高电平,几伏特算低电平。传输层,通信前要发RTS,CTS。每一层都有不同的协议所约束。在STM32中采用的USART就是其中之一。

USART模块由GPIO_InitTypeDef结构体控制,它的定义如下

typedef struct {
u32 USART_BaudRate; // 波特率
u16 USART_WordLength; // 字长
u16 USART_StopBits; // 停止位
u16 USART_Parity; // 校验位
u16 USART_Mode; // USART 模式
u16 USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;

外部设备的输入输出分别使用GPIOA的9号和10号管脚,因此我们要先把管脚输入输出模式配置好

GPIO_InitTypeDef GPIO_USART_INIT;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_USART_INIT.GPIO_Pin = GPIO_Pin_9;
GPIO_USART_INIT.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_INIT.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_USART_INIT); GPIO_USART_INIT.GPIO_Pin = GPIO_Pin_10;
GPIO_USART_INIT.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_INIT.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_USART_INIT);

然后我们设置USART,将波特率设置为9600,禁用硬件流控制模式,工作模式允许发送和接收,不设置校验位,数据位为8比特,在帧尾传输1个停止位。

USART_InitTypeDef USART_INIT;

USART_INIT.USART_BaudRate = ;
USART_INIT.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_INIT.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_INIT.USART_Parity = USART_Parity_No;
USART_INIT.USART_StopBits = USART_StopBits_1;
USART_INIT.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_INIT); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

当然,处理器不可能时时刻刻检查串口有没有信息传来,因此我们刚刚学习的中断就派上了用场,如果串口传输了信息,那么则请求中断并进行处理。

NVIC_InitTypeDef NVIC_USART_INIT;

NVIC_USART_INIT.NVIC_IRQChannel = USART1_IRQn;
NVIC_USART_INIT.NVIC_IRQChannelPreemptionPriority = ;
NVIC_USART_INIT.NVIC_IRQChannelSubPriority = ;
NVIC_USART_INIT.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_USART_INIT); USART_Cmd(USART1,ENABLE);

中断回调函数,负责接收信息

u8 RXData;

void USART1_IRQHandler()
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
RXData = USART_ReceiveData(USART1);
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE|USART_IT_TXE);
}

依然采取防御式编程,只有确信是被中断调用时才进行消息接收,比较坑的一点在于,回调函数的返回值被写死成void类型了,所以必须定义一个外部变量,进行接收值的传输。

输出函数,注意需要等待,直到信息发送完成的flag被设置。

void USART1_SData(u8 Data)
{
USART_SendData(USART1,Data);
while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));
USART_ClearFlag(USART1,USART_FLAG_TC);
}
#include <usart.h>

void usart_configer()
{
GPIO_InitTypeDef GPIO_USART_INIT;
USART_InitTypeDef USART_INIT;
NVIC_InitTypeDef NVIC_USART_INIT; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); GPIO_USART_INIT.GPIO_Pin = GPIO_Pin_9;
GPIO_USART_INIT.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_INIT.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_USART_INIT); GPIO_USART_INIT.GPIO_Pin = GPIO_Pin_10;
GPIO_USART_INIT.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_USART_INIT.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_USART_INIT); //有些参数和串口助手上设置的比较
USART_INIT.USART_BaudRate = ;
USART_INIT.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_INIT.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_INIT.USART_Parity = USART_Parity_No;//奇偶模式,不设置奇偶
USART_INIT.USART_StopBits = USART_StopBits_1;//停止位
USART_INIT.USART_WordLength = USART_WordLength_8b;//数据位
USART_Init(USART1,&USART_INIT); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//接收中断 NVIC_USART_INIT.NVIC_IRQChannel = USART1_IRQn;
NVIC_USART_INIT.NVIC_IRQChannelPreemptionPriority = ;
NVIC_USART_INIT.NVIC_IRQChannelSubPriority = ;
NVIC_USART_INIT.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_USART_INIT); USART_Cmd(USART1,ENABLE); } void USART1_SData(u8 Data)
{
USART_SendData(USART1,Data);
//USART_SendData(USART1,(u8)USART_GetFlagStatus(USART1,USART_IT_TC));
while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));//等待发送完毕
USART_ClearFlag(USART1,USART_FLAG_TC);//清除标志位
} u8 RXData; void USART1_IRQHandler()//接收
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//判断是否真的是接收中断 每次接收1byte
{
RXData = USART_ReceiveData(USART1);
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE|USART_IT_TXE);//清空中断源(接收中断和发送中断)
}
//usart.c
#ifndef _USART_H
#define _USART_H #include <stm32f10x.h> void usart_configer();
void USART1_SData(u8 Data);
void USART1_IRQHandler(); extern u8 RXData; #endif
//usart.h

STM32嵌入式开发学习笔记(六):串口通信(上)的更多相关文章

  1. STM32嵌入式开发学习笔记(七):串口通信(下)

    下面我们进行几个串口通信的实际应用. 实验一:发信实验,让开发板通过串口向电脑发送信息: #include <stdio.h> #include <stm32f10x.h> # ...

  2. STM32嵌入式开发学习笔记(一)

    本文中,笔者将介绍使用嵌入式开发工具Keil uVision5,使用C语言,对微处理器STM32F103C8进行嵌入式开发. 开发使用C语言,首先需要新建一个C语言文件,将其设为主函数的入口,因此,将 ...

  3. STM32嵌入式开发学习笔记(三):使用按键控制小灯

    按键和小灯一样,也是通过GPIO外设与主板连接,也是通过GPIO_InitStruct类型结构体控制其工作. 查阅技术手册,按钮连接GPIOA控制下的管脚0. 但与之不同的是,按键是一种输入设备,输入 ...

  4. stm32寄存器版学习笔记02 串口通信

    stm32F103RCT6提供5路串口.串口的使用,只要开启串口时钟,设置相应的I/O口的模式,然后配置下波特率.数据位长度.奇偶校验等信息,即可使用. 1.串口的配置步骤 ①串口时钟使能 APB2外 ...

  5. STM32嵌入式开发学习笔记(五):中断

    我们过去了解了用循环实现延时,或用系统滴答计时器实现延时,但这两种方法都有一种问题:会阻塞处理器的运行.下面我们学习一种不阻塞处理器运行其他事件的功能:时钟中断. 所谓中断,就是让处理器放下手头的事情 ...

  6. STM32嵌入式开发学习笔记(四):使用滴答计时器实现精准计时

    前面我们讲过,因为在STM32上没有系统时间的接口,因此无法调用sleep函数,在本文中,笔者将利用滴答计时器实现精准延时. 查阅技术手册,滴答计时器依赖于一个SysTick_Type类型寄存器,定义 ...

  7. STM32嵌入式开发学习笔记(二):将功能封装为库文件

    将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里. 库文件就是你代码开始部分写的#include<xxxx.h>里 ...

  8. 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现

    目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...

  9. Arduino学习笔记⑥ 硬件串口通信

    1.前言     Ardunio与计算机通信最常用的方式就是串口通信.在Arduino控制器上,串口都是位于Rx和Tx两个引脚,Arduino的USB口通过一个转换芯片与这两个串口引脚连接.该转换芯片 ...

随机推荐

  1. VC2010 CString.Format使用报错 error C2664

    error C2664: “void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 ...

  2. PLSQL连接虚拟机中的Oracle数据库

    下面这个连接对以后虚拟机安装非常有用!!! https://blog.csdn.net/lixin5456985/article/details/81670095

  3. GO 学习资源收集

     golang图书,在线阅读Go轻松学https://www.golang123.com/book/16 Go示例学https://www.golang123.com/book/17 Go Web 编 ...

  4. dedecms SESSION变量覆盖导致SQL注入漏洞修补方案

    dedecms的/plus/advancedsearch.php中,直接从$_SESSION[$sqlhash]获取值作为$query带入SQL查询,这个漏洞的利用前提是session.auto_st ...

  5. 【Tomcat】1.Tomcat在Windows系统的安装和使用

    1.下载与安装 安装Tomcat的[前提条件]是安装好JDK或者JRE(本文略过)Tomcat在Windows系统中可以通过[压缩包]或[安装包]来安装建议使用[安装包]来简化安装步骤登录官网http ...

  6. 性能测试基础 ---TCP通信过程的状态码与过程,以及出现错误码的分析(TIME_WAIT,CLOSE_WAIT)

    TCP通信过程 如下图所示,TCP通信过程包括三个步骤:建立TCP连接通道(三次握手).数据传输.断开TCP连接通道(四次挥手). 这里进一步探究TCP三路握手和四次挥手过程中的状态变迁以及数据传输过 ...

  7. 【react】---react中key值的作用

    一.React中key值得作用 react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的,而是给React自己使用,有了key属性后,就可以与组件建立了一种对应关系,简单说,react利 ...

  8. 常用numpy和pandas

    常用库 1.NumPy NumPy是高性能科学计算和数据分析的基础包.部分功能如下: ndarray, 具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组. 用于对整组数据进行快速运算的标准数学 ...

  9. ZanUI-WeApp -- 一个颜值高、好用、易扩展的微信小程序 UI 库

    ZanUI-WeApp -- 一个颜值高.好用.易扩展的微信小程序 UI 库:https://cnodejs.org/topic/589d625a5c8036f7019e7a4a 微信小程序之官方UI ...

  10. 4154: [Ipsc2015]Generating Synergy

    Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 区间修改单点查询kdtree #include<iostre ...