本文我们将了解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. mysql查询诊断分析工具

    Query Profiler是MYSQL自带的一种query诊断分析工具,通过它可以分析出一条SQL语句的性能瓶颈在什么地方.通常我们是使用的explain,以及slow query log都无法做到 ...

  2. lazy图片懒加载使用

    看到一个小伙子写的言简意赅很不错,摘录如下: https://www.npmjs.com/package/vue-lazyload 首先我们先在npm上下载vue-lazyload的包 1 npm i ...

  3. linux下lamp.sh一键配置lamp环境流程

    linux下lamp.sh一键配置lamp环境流程 一.总结 一句话总结: 2.将网站从github上clone到/data/www/网站域名/ 3.更改网站目录权限:chown -R apache: ...

  4. 8086汇编和Win32汇编

    8086汇编是指在某环境下汇编编译产生的程序,用机器去执行每条指令的长度为16位(可小于16),如DOS操作系统:WIN32汇编是32位环境下的汇编,如Windows(Windows也有64位的,XP ...

  5. php+js实现极验滑块拖动验证码-tncode

    先上图: 演示地址:http://aso.39gs.com/tncode/index.html 相信在淘宝,斗鱼这些大网站都见到过这样的验证码了,拖动验证码比传统在移动端有更好的化验,减少用户的输入. ...

  6. windows 配置msys2环境

    msys2是一个在windows下模拟类unix的环境,之所以叫环境,是用为他提供了部分unix shell类似的功能,这个环境使你像在unix上使用shell一样.看到msys2你可能想到是不是还有 ...

  7. Celery 'Getting Started' not able to retrieve results; always pending

    参考 根据Celery的官方文档,当使用windows 10 64-bit, Python 2.7,Erlang 64-bit binary, RabbitMQ server and celery r ...

  8. ng -v 不是内部或外部命令

    输入 npm install -g @angular/cli ng new my-app 提示ng -v 不是内部或外部命令 解决方法 1.安装过程中是否出错 原因可能是npm install -g  ...

  9. 更改package.js后重新加载

    node --save可有省略掉手动修改package.json的步骤   当你为你的模块安装一个依赖模块时,正常情况下你得先安装他们(在模块根目录下npm install module-name), ...

  10. LCD中6800和8080的区别【转】

    8080是通过“读使能(RE)”和“写使能(WE)”两条控制线进行读写操作6800是通过“总使能(E)”和“读写选择(W/R)”两条控制线进行 很多MCU或者LCD模块外部接口一般采用并行方式,并行接 ...