库函数解释
结构体初始化配置
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);
接收数据
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
MicroLIB
MicroLIB是Keil为嵌入式平台优化的一个精简库
多个串口同时使用printf
1 2 3
| char String[100]; sprintf(String,"Num=%d\r\n",666); Serial_SendString(String);
|
可变参数
1 2 3 4 5 6 7 8 9
| 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.查询方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stm32f10x.h> #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); OLED_ShowHexNum(1,1,RXData,2); } } }
|
2.中断方法
子程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| #include "stm32f10x.h" #include <stdio.h> #include <stdarg.h>
uint8_t Serial_RxData; uint8_t Serial_RxFlag;
void Serial_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 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_InitTypeDef USART_InitStructrue; USART_InitStructrue.USART_BaudRate=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; USART_InitStructrue.USART_WordLength=8; USART_Init(USART1,&USART_InitStructrue); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 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); while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); }
void Serial_SendArray(uint8_t *Array, uint16_t Length) { uint16_t i; for(i=0;i<Length;i++) { Serial_SendByte(Array[i]); } }
void Serial_SendString(char * String) { uint8_t i; for(i=0;String[i] != '\0';i++) { Serial_SendByte(String[i]); } }
uint32_t Serial_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while(Y--) { Result *=X; } return Result; }
void Serial_SendNumber(uint32_t Number,uint8_t Length) { uint8_t i; for(i=0;i<Length;i++) { Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10 + '0'); } }
int fputc(int ch,FILE * f) { Serial_SendByte(ch); return ch; }
void Serial_Printf(char * format,...) { char String[100]; va_list arg; va_start(arg,format); vsprintf(String,format,arg); va_end(arg); Serial_SendString(String); }
uint8_t Serial_GerRxFlag(void) { if(Serial_RxFlag == 1) { Serial_RxFlag = 0; return 1; } return 0; }
uint8_t Serial_GetRxData(void) { return Serial_RxData; }
void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) { Serial_RxData = USART_ReceiveData(USART1); Serial_RxFlag=1; USART_ClearITPendingBit(USART1,USART_IT_RXNE); } }
|
2.主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stm32f10x.h> #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()==1) { RXData = Serial_GetRxData(); Serial_SendByte(RXData); OLED_ShowHexNum(1,8,RXData,2); }
} }
|
串口数据包
打包多字节为一个数据包,方便发送多字节的数据。将同一批的数据进行打包和分割
包头、包尾:简易通信协议
状态机的方法来接收数据包
1.发送数据包
2.接收数据包
串口中断子程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| #include "stm32f10x.h" #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); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 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_InitTypeDef USART_InitStructrue; USART_InitStructrue.USART_BaudRate=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; USART_InitStructrue.USART_WordLength=8; USART_Init(USART1,&USART_InitStructrue); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 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); while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); }
void Serial_SendArray(uint8_t *Array, uint16_t Length) { uint16_t i; for(i=0;i<Length;i++) { Serial_SendByte(Array[i]); } }
void Serial_SendString(char * String) { uint8_t i; for(i=0;String[i] != '\0';i++) { Serial_SendByte(String[i]); } }
uint32_t Serial_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while(Y--) { Result *=X; } return Result; }
void Serial_SendNumber(uint32_t Number,uint8_t Length) { uint8_t i; for(i=0;i<Length;i++) { Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10 + '0'); } }
int fputc(int ch,FILE * f) { Serial_SendByte(ch); return ch; }
void Serial_Printf(char * format,...) { char String[100]; va_list arg; va_start(arg,format); vsprintf(String,format,arg); va_end(arg); Serial_SendString(String); }
uint8_t Serial_GetRxFlag(void) { if(Serial_RxFlag == 1) { Serial_RxFlag = 0; return 1; } return 0; }
void Serial_SendPacket(void) { Serial_SendByte(0xFF); Serial_SendArray(Serial_TxPacket,4); Serial_SendByte(0xFE); }
void USART1_IRQHandler(void) { static uint8_t RxState = 0; static uint8_t pRxState = 0; if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) { uint8_t RxData = USART_ReceiveData(USART1); if(RxState == 0) { if(RxData == 0xFF) { RxState=1; } } else if(RxState==1) { Serial_RxPacket[pRxState]=RxData; if(++pRxState>=4) { pRxState=0; RxState=2; } } else if(RxState==2) { if (RxData==0xFE) { RxState = 0; Serial_RxFlag=1; } } USART_ClearITPendingBit(USART1,USART_IT_RXNE); } }
|
Serial.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #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.文本收发数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
| #include "stm32f10x.h" #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); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 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_InitTypeDef USART_InitStructrue; USART_InitStructrue.USART_BaudRate=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; USART_InitStructrue.USART_WordLength=8; USART_Init(USART1,USART_InitStructrue); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 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); while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); }
void Serial_SendArray(uint8_t *Array, uint16_t Length) { uint16_t i; for(i=0;i<Length;i++) { Serial_SendByte(Array[i]); } }
void Serial_SendString(char * String) { uint8_t i; for(i=0;String[i] != '\0';i++) { Serial_SendByte(String[i]); } }
uint32_t Serial_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while(Y--) { Result *=X; } return Result; }
void Serial_SendNumber(uint32_t Number,uint8_t Length) { uint8_t i; for(i=0;i<Length;i++) { Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10 + '0'); } }
int fputc(int ch,FILE * f) { Serial_SendByte(ch); return ch; }
void Serial_Printf(char * format,...) { char String[100]; va_list arg; va_start(arg,format); vsprintf(String,format,arg); va_end(arg); Serial_SendString(String); }
void USART1_IRQHandler(void) { static uint8_t RxState = 0; static uint8_t pRxState = 0; if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) { uint8_t RxData = USART_ReceiveData(USART1); if(RxState == 0) { if(RxData == '@' && Serial_RxFlag == 0) { RxState=1; } } else if(RxState==1) { if(RxData == '\r') { RxState=2; } else { Serial_RxPacket[pRxState]=RxData; pRxState++; } } else if(RxState==2) { if (RxData=='\n') { RxState = 0; Serial_RxFlag=1; Serial_RxPacket[pRxState]='\0'; pRxState=0; } } USART_ClearITPendingBit(USART1,USART_IT_RXNE); } }
|
#串口下载
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:HC-05复位
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:AT+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= 需要加双引号!