2587 字
13 分钟
【STM32单片机】标准库 10 - 串口通信

库函数解释#

结构体初始化配置

void USART_DeInit(USART_TypeDef* USARTx);
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
void USART_StructInit(USART_InitTypeDef* USART_InitStruct);

同步时钟配置

void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);

发送数据

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

  • 写DR寄存器

接收数据

uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

  • 读DR寄存器

MicroLIB#

MicroLIB是Keil为嵌入式平台优化的一个精简库

多个串口同时使用printf#

char String[100];
sprintf(String,"Num=%d\r\n",666);//sprintf.可以将指定的数据复制到数组中
Serial_SendString(String);//打印字符串

可变参数#

void Serial_Prinf(char * format,...)
{
char String[100];
va_list arg;//参数列表变量
va_start(arg,format);
vsprintf(String,format,arg);
va_end(arg);//释放参数列表
Serial_SendString(String);
}

汉字编码发送#

统一选定为UTF-8编码

串口接收#

1.查询方法#

#include <stm32f10x.h> //Device header
#include <OLED.h>
#include <Delay.h>
#include <Serial.h>
uint8_t RXData;
int main(void)
{
OLED_Init();
Serial_Init();
while(1)
{
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)
{
RXData=USART_ReceiveData(USART1);//读DR可以自动清除标志位
OLED_ShowHexNum(1,1,RXData,2);
}
}
}

2.中断方法#

子程序#

#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启GPIOA的时钟
/*配置PA9为复用推挽输出,供USART1的TX使用*/
GPIO_InitTypeDef GPIO_InitStructure; //结构体类型(已经定义好的) 结构体变量名 ->结构体变量的定义
/*串口发送引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*串口接收引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*USART结构体初始化*/
USART_InitTypeDef USART_InitStructrue;
USART_InitStructrue.USART_BaudRate=9600;//直接写入设定的波特率,函数内部会自动算好9600对应的寄存器配置
USART_InitStructrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//流控制关
USART_InitStructrue.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;//串口发送+接收
USART_InitStructrue.USART_Parity=USART_Parity_No;//无校验位
USART_InitStructrue.USART_StopBits=USART_StopBits_1;//1位停止位
USART_InitStructrue.USART_WordLength=8;//字长8位
USART_Init(USART1,&USART_InitStructrue);
/*中断配置*/
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启RXNE的标志位到NVIC输出
/*NVIC配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);//写入DR寄存器
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE)

2.主程序#

#include <stm32f10x.h> //Device header
#include <OLED.h>
#include <Delay.h>
#include <Serial.h>
uint8_t RXData;
int main(void)
{
OLED_Init();
OLED_ShowString(1,1,"RxData:");
Serial_Init();
while(1)
{
if(Serial_GerRxFlag()

串口数据包#

打包多字节为一个数据包,方便发送多字节的数据。将同一批的数据进行打包和分割

包头、包尾:简易通信协议

  • 文本数据包
  • Hex数据包

状态机的方法来接收数据包#

1.发送数据包#

2.接收数据包#

串口中断子程序

#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_TxPacket[4];
uint8_t Serial_RxPacket[4];
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启GPIOA的时钟
/*配置PA9为复用推挽输出,供USART1的TX使用*/
GPIO_InitTypeDef GPIO_InitStructure; //结构体类型(已经定义好的) 结构体变量名 ->结构体变量的定义
/*串口发送引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*串口接收引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*USART结构体初始化*/
USART_InitTypeDef USART_InitStructrue;
USART_InitStructrue.USART_BaudRate=9600;//直接写入设定的波特率,函数内部会自动算好9600对应的寄存器配置
USART_InitStructrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//流控制关
USART_InitStructrue.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;//串口发送+接收
USART_InitStructrue.USART_Parity=USART_Parity_No;//无校验位
USART_InitStructrue.USART_StopBits=USART_StopBits_1;//1位停止位
USART_InitStructrue.USART_WordLength=8;//字长8位
USART_Init(USART1,&USART_InitStructrue);
/*中断配置*/
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启RXNE的标志位到NVIC输出
/*NVIC配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);//写入DR寄存器
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE)

Serial.h

#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
extern uint8_t Serial_TxPacket[];
extern uint8_t Serial_RxPacket[];
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char * String);
void Serial_SendNumber(uint32_t Number,uint8_t Length);
void Serial_Printf(char * format,...);
uint8_t Serial_GetRxFlag(void);
void Serial_SendPacket(void);
#endif

小操作#

按住alt选择一列进行修改

3.文本收发数据包#

#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RxPacket[100];
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //开启USART1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启GPIOA的时钟
/*配置PA9为复用推挽输出,供USART1的TX使用*/
GPIO_InitTypeDef GPIO_InitStructure; //结构体类型(已经定义好的) 结构体变量名 ->结构体变量的定义
/*串口发送引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*串口接收引脚部分*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure);
/*USART结构体初始化*/
USART_InitTypeDef USART_InitStructrue;
USART_InitStructrue.USART_BaudRate=9600;//直接写入设定的波特率,函数内部会自动算好9600对应的寄存器配置
USART_InitStructrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//流控制关
USART_InitStructrue.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;//串口发送+接收
USART_InitStructrue.USART_Parity=USART_Parity_No;//无校验位
USART_InitStructrue.USART_StopBits=USART_StopBits_1;//1位停止位
USART_InitStructrue.USART_WordLength=8;//字长8位
USART_Init(USART1,USART_InitStructrue);
/*中断配置*/
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启RXNE的标志位到NVIC输出
/*NVIC配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);//写入DR寄存器
while( USART_GetFlagStatus(USART1,USART_FLAG_TXE)

串口下载#

Boot引脚#

BootLoder的作用相当于刷机

调试使用#

可以保持跳线帽置1,但是复位后程序丢失,所以仅用来调试

读FLASH生成bin文件#

读保护/写保护#

蓝牙串口通信#

电赛|项目|课设:蓝牙模块HC05主从配置与连接_蓝牙 master和 slave 服务-CSDN博客

AT指令集

AT+NAME = xlg 设置蓝牙名称为xlg

AT+ROLE=0 蓝牙模式为从模式 AT+ROLE=1 蓝牙模式为主模式
AT+CMODE=0 蓝牙连接模式为任意地址连接模式
AT+PSWD=1234 蓝牙配对密码为1234
AT+UART=9600,0,0 蓝牙通信串口波特率为9600,停止位1位,无校验位
AT+RMAAD 清空配对列表

一、更改波特率
AT+UART=a,b,c
蓝牙通信串口波特率为a,
b:停止位1位,无校验位
返回响应为OK

二、修改蓝牙模块密码

修改密码的AT指令格式如下:(以修改后的密码为1314为例)

AT+PSWD=1314(这里加回车)

1
三、修改蓝牙模块名字

修改模块名字的AT指令如下:

AT+NAME =

1
1, AT+ROLE设置主从模式:
AT+ROLE=1是设成主,AT+ROLE=0是设成从,AT+ROLE=2设成回环模式Slave-Loop:被动连接,接收远程蓝 牙主设备数据并将数据原样返回给远程蓝牙
AT+ROLE?:查询主从状态
2, AT+RESET复位

3, AT+VERSION?:获取HC-05的软件版本号,只能获取,不能修改。

4, AT+ORGL:恢复出厂默认设置,当把模块设置乱了,使用此命令进行恢复默认值。

5, AT+ADDR?:获取HC-05的蓝牙地址码,只能获取,不能修改。

6, AT+NAME?:获取HC-05的名字,AT+NAME=xlg,修改模块的名字为xlg,具体名字自行修改。

7, AT+CLASS?:设置查询设备的类型,尽量不要去修改此参数。默认是1F00。

8, AT+IAC?:查询设置查询访问码,默认是9E8B33,尽量不要去修改此参数。

9, AT+PSWD?:查询设置配对密码,AT+PSWD=”0000”,密码要有双引号,密码是四位数字.

10, AT+UART:AT+UART?是查询当前模块的波特率,AT+UART=波特率,0,0。

11, AT+CMODE:AT+CMODE?是查询当前连接模式。AT+CMODE=0,1,2(0——指定蓝牙地址连接模式(指定蓝牙地址由绑定指令设置)1——任意蓝牙地址连接模式(不受绑定指令设置地址的约束)2——回环角色(Slave-Loop)默认连接模式:0)。

12, AT+BIND+BIND?查询当前绑定地址,AT+BIND=NAP,UAP,LAP(用逗号隔开)。

13, AT+RMADD:从蓝牙配对列表中删除所有认证设备.

14, AT+STATE?:获取蓝牙模块工作状态.

15, AT+LINK=NAP,UAP,LAP:与远程设备建立连接。

16, AT+DISC:断开连接.

17, AT+RNAME?NAP,UAP,LAP:获取远程蓝牙设备名称.

18, AT+ADCN?:获取蓝牙配对列表中认证设备数。

19, AT+MRAD?获取最近使用过的蓝牙认证设备地址。

20, AT+INQM:设置查询模式,AT+INQM=1,9,48(1-带RSSI信号强度指示,9-超过9个蓝牙设备响应则终止查询,48-设定超时为48*1.28=61.44秒)

ps: HC05模块的AT指令,蓝牙命名AT+NAME= 以及密码设置AT+PSWD= 需要加双引号!

【STM32单片机】标准库 10 - 串口通信
http://www.turinblog.cn/posts/stm32单片机标准库-10---串口通信/
作者
Szturin
发布于
2024-05-20
许可协议
CC BY-NC-SA 4.0