STM32嵌入式开发学习笔记(六):串口通信(上)
本文我们将了解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嵌入式开发学习笔记(六):串口通信(上)的更多相关文章
- STM32嵌入式开发学习笔记(七):串口通信(下)
下面我们进行几个串口通信的实际应用. 实验一:发信实验,让开发板通过串口向电脑发送信息: #include <stdio.h> #include <stm32f10x.h> # ...
- STM32嵌入式开发学习笔记(一)
本文中,笔者将介绍使用嵌入式开发工具Keil uVision5,使用C语言,对微处理器STM32F103C8进行嵌入式开发. 开发使用C语言,首先需要新建一个C语言文件,将其设为主函数的入口,因此,将 ...
- STM32嵌入式开发学习笔记(三):使用按键控制小灯
按键和小灯一样,也是通过GPIO外设与主板连接,也是通过GPIO_InitStruct类型结构体控制其工作. 查阅技术手册,按钮连接GPIOA控制下的管脚0. 但与之不同的是,按键是一种输入设备,输入 ...
- stm32寄存器版学习笔记02 串口通信
stm32F103RCT6提供5路串口.串口的使用,只要开启串口时钟,设置相应的I/O口的模式,然后配置下波特率.数据位长度.奇偶校验等信息,即可使用. 1.串口的配置步骤 ①串口时钟使能 APB2外 ...
- STM32嵌入式开发学习笔记(五):中断
我们过去了解了用循环实现延时,或用系统滴答计时器实现延时,但这两种方法都有一种问题:会阻塞处理器的运行.下面我们学习一种不阻塞处理器运行其他事件的功能:时钟中断. 所谓中断,就是让处理器放下手头的事情 ...
- STM32嵌入式开发学习笔记(四):使用滴答计时器实现精准计时
前面我们讲过,因为在STM32上没有系统时间的接口,因此无法调用sleep函数,在本文中,笔者将利用滴答计时器实现精准延时. 查阅技术手册,滴答计时器依赖于一个SysTick_Type类型寄存器,定义 ...
- STM32嵌入式开发学习笔记(二):将功能封装为库文件
将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里. 库文件就是你代码开始部分写的#include<xxxx.h>里 ...
- 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现
目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...
- Arduino学习笔记⑥ 硬件串口通信
1.前言 Ardunio与计算机通信最常用的方式就是串口通信.在Arduino控制器上,串口都是位于Rx和Tx两个引脚,Arduino的USB口通过一个转换芯片与这两个串口引脚连接.该转换芯片 ...
随机推荐
- mysql全家桶(四)存储过程
一.存储过程1.介绍简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法: 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以 ...
- springmvc缓存 - cache
前几篇文章已经搭建了一个基本的springmvc demo,现在我们来完善下. 相信大家写程序的时候都接触过缓存的概念,也都知道,数据量大的时候缓存对于提高效率是很显著的.而缓存一般包括前台静态 ...
- python进阶:类和对象
@修饰符:将被修饰的函数作为参数,运行修饰函数 实例方法: 静态方法:@staticmethod 类方法:@classmethod 自省:通过一定的机制查询到对象的内部结构 序列类: 列表推导式(例表 ...
- java并发编程笔记(一)——并发编程简介
java并发编程笔记(一)--简介 线程不安全的类示例 public class CountExample1 { // 请求总数 public static int clientTotal = 500 ...
- sqlserver 找不到驱动,显示项目缺少class办法
maven使用 <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId> ...
- 使用python实现希尔、计数、基数排序
希尔排序 希尔排序是一个叫希尔的数学家提出的一种优化版本的插入排序. 首先取一个整数d1=n//2,将元素分为d1个组,每组相邻元素之间的距离为d1,在各组内进行直接插入排序. 取第二个整数d2=d1 ...
- ES6数组方法
ES6数组方法 以下方法添加到了Array.prototype对象上(isArray除外) indexOf 类似字符串的indexOf()方法 stringObject.indexOf(searchv ...
- 内核module读取进程页目录
根据当前CR3寄存器内容,读取对应物理内存中的页目录页,并进行解析 1: void dumpPageDirectoryEntry(u32 entry) 2: { 3: u8 present; 4: u ...
- mysql 内连接和外连接查询
一.内连接查询 (笛卡儿积) 内联接查询inner join,mysql可以简写为join 二.外连接查询 左外联接查询left outer join,mysql可以简写为left join右外联接查 ...
- helm-mode打开文件支持中文搜索
helm-mode打开文件支持中文搜索 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #83949 ...