本文我们将了解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. 使用vue完成一个分页效果

    基于 element-ui 分页组件实现分页效果 效果如下: 使用说明: 0.首先在头部引入需要的外部文件 1.从element官方网页中复制想要的组件代码直接放入body中 2.编写逻辑代码 3.完 ...

  2. 2018icpc南京/gym101981 A Adrien and Austin 博弈

    题意: n个连续排列的石子,每次只许拿连续的(中间没有空格)的k个,问你谁必胜 题解: 简单博弈,特判总数为0,k=1两种情况,其他情况先拿必胜,方法是拿掉中间的,然后对方怎么拿你镜面拿就行. #in ...

  3. qrcode.js生成二维

    使用到qrcode.js生成二维码 pako.js压缩字符串:https://github.com/nodeca/pako 参照代码如下: <!DOCTYPE HTML PUBLIC " ...

  4. HTTP超详细总结

    HTTP协议概述 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的 ...

  5. STemWin5.22移植笔记(flyheart)

    看了野火ISO开发板移植的emWin,感觉不错,但是没有写移植教程,通过摸索与百度知道了移植的过程!下面和大家分享一下 emWin是segger公司出的一款图形化界面,非常好看,大家所熟悉的ucGUI ...

  6. MySQL高级学习笔记(五):查询截取分析

    文章目录 慢查询日志 是什么 怎么玩 说明 查看是否开启及如何开启 默认 开启 那么开启了慢查询日志后,什么样的SQL才会记录到慢查询日志里面呢? Case 配置版 日志分析工具mysqldumpsl ...

  7. NIO浅析(一)

    一:NIO与IO的区别 1.NIO面对的是缓冲区,IO面对的是流 2.NIO是非阻塞的,IO是阻塞的 3.NIO中引入了选择器 二:既然NIO面对的是缓冲区,那就先来了解缓冲区 1.NIO中Buffe ...

  8. leetcode.位运算.136只出现一次的元素-Java

    1. 具体题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明:你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1 ...

  9. ansible了解

    基础知识: ansible简介 ansible 是个什么东西呢?基于 Python paramiko 开发,分布式,无需客户端,轻量级,配置语法使用 YMAL 及 Jinja2模板语言,更强的远程命令 ...

  10. 怎么在vue-cli中利用 :class去做一个底层背景或者文字的点击切换

    // html <div class="pusherLists" :class="{hidden: isHidden}"> <span @cl ...