00. 目录
文章目录
- 00. 目录
- 01. 串口简介
- 02. 串口收发HEX数据包接线图
- 03. 串口收发HEX数据包示例1
- 04. 串口收发HEX数据包示例2
- 05. 串口收发文本数据包接线图
- 06. 串口收发文本数据包示例
- 07. 程序示例下载
- 08. 附录
01. 串口简介
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式, 电子工程师在调试设备时也经常使用该通讯方式输出调试信息。
在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32标准库则是在寄存器与用户代码之间的软件层。 对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性, 确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。 简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。
02. 串口收发HEX数据包接线图
03. 串口收发HEX数据包示例1
uart.h
#ifndef __UART_H__
#define __UART_H__#include "stm32f10x.h" extern uint8_t recvPacket[];void uart_init(void);void uart_send_byte(uint8_t byte);void uart_send_array(uint8_t *arr, uint16_t len);void uart_send_string(char *str);void uart_send_number(uint32_t num, uint8_t len);void uart_printf(char *format, ...);uint8_t uart_getRxFlag(void);uint8_t uart_getRxData(void);void uart_send_packet(uint8_t arr[], int len);#endif /**/
uart.c
#include "uart.h"#include <stdio.h>
#include <stdarg.h>uint8_t recvData;
uint8_t recvFlag;uint8_t recvPacket[32];void uart_init(void)
{GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO初始化 PA9 TXGPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);//GPIO初始化 PA10 RXGPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);USART_InitStruct.USART_BaudRate = 9600;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);//设置串口中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//设置中断分组NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);USART_Cmd(USART1, ENABLE);
}void uart_send_byte(uint8_t byte)
{USART_SendData(USART1, byte);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void uart_send_array(uint8_t *arr, uint16_t len)
{uint16_t i;for (i = 0; i < len; i++){uart_send_byte(arr[i]);}
}void uart_send_string(char *str)
{uint16_t i = 0;while(*(str + i) != '\0'){uart_send_byte(str[i]);i++;}
}//x的y次方
uint32_t uart_pow(uint32_t x, uint32_t y)
{uint32_t result = 1;while(y){result *= x;y--;}return result;
}void uart_send_number(uint32_t num, uint8_t len)
{uint8_t i;for (i = 0; i < len; i++){uart_send_byte(num / uart_pow(10, len - i - 1) % 10 + '0');}}int fputc(int ch, FILE *fp)
{uart_send_byte(ch);return ch;
}void uart_printf(char *format, ...)
{char str[128];va_list arg;va_start(arg, format);vsprintf(str, format, arg);va_end(arg);uart_send_string(str);
}void USART1_IRQHandler(void)
{static uint8_t recvState = 0;static uint8_t i = 0;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){recvData = USART_ReceiveData(USART1);//状态机if (0 == recvState){if (recvData == 0xFF){recvState = 1;i = 0;}}else if (1 == recvState){recvPacket[i] = recvData;i++;if (i >= 4){recvState = 2;}} else if (2 == recvState){if (recvData == 0xFE){i = 0;recvState = 0;recvFlag = 1;}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}}uint8_t uart_getRxFlag(void)
{if (1 == recvFlag){recvFlag = 0;return 1;}return 0;
}uint8_t uart_getRxData(void)
{return recvData;
}//发送HEX报文数据
void uart_send_packet(uint8_t arr[], int len)
{//发送报文 FFuart_send_byte(0xFF);uart_send_array(arr, len);//发送报尾uart_send_byte(0xFE);
}
main.c
#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "oled.h"
#include "uart.h"int main(void){ uint8_t arr[] = {0x1, 0x2, 0x3, 0x4};OLED_Init();uart_init();//中断分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);OLED_ShowChar(1, 1, 'A');uart_send_packet(arr, 4);while(1){if (1 == uart_getRxData()){OLED_ShowHexNum(1, 1, recvPacket[0], 2);OLED_ShowHexNum(1, 4, recvPacket[1], 2);OLED_ShowHexNum(1, 7, recvPacket[2], 2);OLED_ShowHexNum(1, 10, recvPacket[3], 2); } }return 0;}
04. 串口收发HEX数据包示例2
uart.h
#ifndef __UART_H__
#define __UART_H__#include "stm32f10x.h" extern uint8_t recvPacket[];void uart_init(void);void uart_send_byte(uint8_t byte);void uart_send_array(uint8_t *arr, uint16_t len);void uart_send_string(char *str);void uart_send_number(uint32_t num, uint8_t len);void uart_printf(char *format, ...);uint8_t uart_getRxFlag(void);uint8_t uart_getRxData(void);void uart_send_packet(uint8_t arr[], int len);#endif /**/
uart.c
#include "uart.h"#include <stdio.h>
#include <stdarg.h>uint8_t recvData;
uint8_t recvFlag;uint8_t recvPacket[32];void uart_init(void)
{GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO初始化 PA9 TXGPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);//GPIO初始化 PA10 RXGPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);USART_InitStruct.USART_BaudRate = 9600;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);//设置串口中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//设置中断分组NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);USART_Cmd(USART1, ENABLE);
}void uart_send_byte(uint8_t byte)
{USART_SendData(USART1, byte);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}void uart_send_array(uint8_t *arr, uint16_t len)
{uint16_t i;for (i = 0; i < len; i++){uart_send_byte(arr[i]);}
}void uart_send_string(char *str)
{uint16_t i = 0;while(*(str + i) != '\0'){uart_send_byte(str[i]);i++;}
}//x的y次方
uint32_t uart_pow(uint32_t x, uint32_t y)
{uint32_t result = 1;while(y){result *= x;y--;}return result;
}void uart_send_number(uint32_t num, uint8_t len)
{uint8_t i;for (i = 0; i < len; i++){uart_send_byte(num / uart_pow(10, len - i - 1) % 10 + '0');}}int fputc(int ch, FILE *fp)
{uart_send_byte(ch);return ch;
}void uart_printf(char *format, ...)
{char str[128];va_list arg;va_start(arg, format);vsprintf(str, format, arg);va_end(arg);uart_send_string(str);
}void USART1_IRQHandler(void)
{static uint8_t recvState = 0;static uint8_t i = 0;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){uint8_t recvData1 = USART_ReceiveData(USART1);//状态机if (0 == recvState){if (recvData1 == 0xFF){recvState = 1;i = 0;}}else if (1 == recvState){recvPacket[i] = recvData1;i++;if (i >= 4){recvState = 2;}} else if (2 == recvState){if (recvData1 == 0xFE){recvState = 0;recvFlag = 1;}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}uint8_t uart_getRxFlag(void)
{if (1 == recvFlag){recvFlag = 0;return 1;}return 0;
}uint8_t uart_getRxData(void)
{return recvData;
}//发送HEX报文数据
void uart_send_packet(uint8_t arr[], int len)
{//发送报文 FFuart_send_byte(0xFF);uart_send_array(arr, len);//发送报尾uart_send_byte(0xFE);
}
main.c
#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "oled.h"
#include "uart.h"
#include "key.h"int main(void){ uint8_t arr[] = {0x1, 0x2, 0x3, 0x4};//中断分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);key_init();uart_init();OLED_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");while(1){if (1 == key_scan()){arr[0]++;arr[1]++; arr[2]++;arr[3]++;uart_send_packet(arr, 4); OLED_ShowHexNum(2, 1, arr[0], 2);OLED_ShowHexNum(2, 4, arr[1], 2);OLED_ShowHexNum(2, 7, arr[2], 2);OLED_ShowHexNum(2, 10, arr[3], 2); } if (1 == uart_getRxData()){OLED_ShowHexNum(4, 1, recvPacket[0], 2);OLED_ShowHexNum(4, 4, recvPacket[1], 2);OLED_ShowHexNum(4, 7, recvPacket[2], 2);OLED_ShowHexNum(4, 10, recvPacket[3], 2); } }return 0;}
05. 串口收发文本数据包接线图
06. 串口收发文本数据包示例
uart.h
#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>extern uint8_t Serial_TxPacket[];
extern uint8_t Serial_RxPacket[];
extern uint8_t Serial_RxFlag;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, ...);void Serial_SendPacket(void);#endif
uart.c
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t Serial_TxPacket[4]; //FF 01 02 03 04 FE
char 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_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);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 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 pRxPacket = 0;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){uint8_t RxData = USART_ReceiveData(USART1);if (RxState == 0){if (RxData == '@' && 0 == Serial_RxFlag){RxState = 1;pRxPacket = 0;}}else if (RxState == 1){if (RxData == '\r'){RxState = 2;}else{Serial_RxPacket[pRxPacket] = RxData;pRxPacket ++;}}else if (RxState == 2){if (RxData == '\n'){RxState = 0;Serial_RxPacket[pRxPacket] = '\0';Serial_RxFlag = 1;}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "LED.h"#include <string.h>int main(void)
{OLED_Init();LED_Init();Serial_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");while (1){if (Serial_RxFlag == 1){OLED_ShowString(4, 1, " ");OLED_ShowString(4, 1, Serial_RxPacket);if (strcmp(Serial_RxPacket, "LED_ON") == 0){LED1_ON();OLED_ShowString(2, 1, " ");OLED_ShowString(2, 1, "LED_ON_OK");Serial_SendString("LED_ON_OK\r\n");}else if (strcmp(Serial_RxPacket, "LED_OFF") == 0){LED1_OFF();OLED_ShowString(2, 1, " ");OLED_ShowString(2, 1, "LED_OFF_OK"); Serial_SendString("LED_OFF_OK\r\n"); }else{OLED_ShowString(2, 1, " ");OLED_ShowString(2, 1, "ERROR_COMMAND"); Serial_SendString("ERROR_COMMAND\r\n"); }Serial_RxFlag = 0;}}
}
07. 程序示例下载
24-UART收发HEX数据包
25-UART收发HEX数据包2.rar
26-UART收发文本数据包.rar
08. 附录
参考: 【STM32】江科大STM32学习笔记汇总