功能描述:STM32F405RGT6的USART1通过中断接收数据,并回传收到的数据和数据大小。
- main.c文件内容如下
#include "stm32f4xx.h" // Device header
#include "Serial.h"
uint8_t data[100] = {0}; //数据接收指针
int main(void)
{
Serial_Init(); //初始化串口
Serial_SendChinese(USART1, "现在正在进行串口功能测试。"); //发送中文字符串
Serial_SendString(USART1, "\r\n"); //回车换行
while(1)
{
if(Serial_GetRxFlag() == 1) //判断接收标志位
{
memset(data, 0, sizeof(data)); //清除数据接收区,避免上一次的干扰
Serial_GetRxData(data); //接收数据
Serial_ClearRxFlag(); //清除接收标志位
//回传收到的字符串,并给出字节数
Serial_Printf(USART1, "%s\n%d\n",data,Serial_GetRxSize());
}
}
}
- Serial.c文件的内容如下
#include "Serial.h"
uint8_t RxBuff1[Serial_Buffer_Size]={0};
uint16_t RxSize = 0;
uint8_t RxFlag1 = 0;
/**
* @摘要 初始化USART
* @参数 无
* @返回值 无
* @说明 无
*/
void Serial_Init(void)
{
//开启GPIOA时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//将PA9配置为复用模式,复用为USART1的TX引脚
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
//将PA10配置为复用模式,复用为USART1的RX引脚
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
//定义GPIO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
//初始化上述结构体
GPIO_StructInit(&GPIO_InitStructure);
//配置GPIO模式为复用模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//配置GPIO输出类型为推挽输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//配置GPIO输入类型为上拉输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//配置GPIO的速度为快速50MHZ
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
//指定GPIO引脚为Pin9和Pin10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
//初始化对应的GPIO
GPIO_Init(GPIOA, &GPIO_InitStructure);
//开启USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//定义USART初始化结构体
USART_InitTypeDef USART_InitStructure;
//初始化上述结构体
USART_StructInit(&USART_InitStructure);
//配置波特率为115200
USART_InitStructure.USART_BaudRate = 115200;
//配置数据长度为8位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
//配置校验位为无
USART_InitStructure.USART_Parity = USART_Parity_No;
//配置停止位为1位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//配置串口模式为接收和发送模式
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
//配置硬件流控制为无
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
//初始化对应的USART
USART_Init(USART1, &USART_InitStructure);
//使能USART1的接收寄存器非空中断到NVIC
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//使能USART1的检测到空闲线路中断到NVIC
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
//NVIC优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//定义NVIC初始化结构体
NVIC_InitTypeDef NVIC_InitStructure;
//选择NVIC通道为USART1_IRQn
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
//使能该通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//配置抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//配置响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
//初始化NVIC
NVIC_Init(&NVIC_InitStructure);
//开启USART1
USART_Cmd(USART1, ENABLE);
}
/**
* @摘要 串口发送一个字节数据
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 Byte: 要发送的字节数据
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendByte(USART_TypeDef* USARTx, uint8_t Byte)
{
uint16_t timeout = 10000;
USART_SendData(USARTx, Byte);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
{
timeout--;
if(timeout == 0)
return 0;
}
return 1;
}
uint8_t Serial_SendArray(USART_TypeDef* USARTx, uint8_t *array, uint16_t length)
{
uint8_t state = 0;
for(uint16_t i=0; i<length; i++)
{
state = Serial_SendByte(USARTx, array[i]);
if(state == 0)
return 0;
}
return 1;
}
/**
* @摘要 串口发送一个字符串
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 str: 要发送的字符串
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendString(USART_TypeDef* USARTx, const char *str)
{
uint8_t state = 0;
for(uint16_t i=0; str[i]!='\0'; i++)
{
state = Serial_SendByte(USARTx, str[i]);
if(state == 0)
return 0;
}
return 1;
}
/**
* @摘要 串口发送一个无符号整数
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 Number:指定要发送的数字,范围:0~4294967295
* @参数 type: 要以什么进制发送上述整数,比如2,8,10,16
* @参数 length:要发送的整数的长度
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendNum(USART_TypeDef* USARTx, uint32_t Number, uint8_t type, uint8_t length)
{
uint8_t state = 0;
uint8_t temp;
for(uint8_t i=0; i<length; i++)
{
temp = (Number/Pow(type,length-i-1))%type;
if(temp > 9)
state = Serial_SendByte(USARTx, temp-10+'A');
else
state = Serial_SendByte(USARTx, temp+'0');
if(state == 0)
return 0;
}
return 1;
}
/**
* @摘要 串口发送一个有符号整数
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 Number:要发送的整数
* @参数 length:要发送的整数的长度
* @参数 ShowSign:是否显示'+'号,ENABLE(显示)或DISABLE(不显示)
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 Number会以十进制格式发送出去
*/
uint8_t Serial_SendSignedNum(USART_TypeDef* USARTx, int32_t Number, uint8_t length, FunctionalState ShowSign)
{
uint8_t state = 0;
if(Number < 0)
{
state = Serial_SendByte(USARTx, '-');
if(state == 0)
return 0;
state = Serial_SendNum(USARTx, -Number,10,length);
if(state == 0)
return 0;
}
else
{
if(ShowSign == ENABLE)
{
state = Serial_SendByte(USARTx, '+');
if(state == 0)
return 0;
state = Serial_SendNum(USARTx, Number,10,length);
if(state == 0)
return 0;
}
else
{
state = Serial_SendNum(USARTx, Number,10,length);
if(state == 0)
return 0;
}
}
return 1;
}
/**
* @摘要 串口发送一个小数
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 Number:要发送的小数,范围:-4294967295.0~4294967295.0
* @参数 type:要以什么进制发送上述小数,比如2,8,10,16
* @参数 IntLength:指定数字的整数部分长度
* @参数 FraLength:指定数字的小数部分长度,小数进行去尾补0显示
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendFloatNum(USART_TypeDef* USARTx, double Number,uint8_t type, uint8_t IntLength, uint8_t FraLength)
{
uint8_t state = 0;
uint32_t tempNum = Number;
uint8_t temp;
for(uint8_t i=0; i<IntLength; i++)
{
temp = (tempNum/Pow(type,IntLength-i-1))%type;
if(temp > 9)
state = Serial_SendByte(USARTx, temp-10+'A');
else
state = Serial_SendByte(USARTx, temp+'0');
if(state == 0)
return 0;
}
state = Serial_SendByte(USARTx, '.');
if(state == 0)
return 0;
tempNum = (Number-tempNum)*Pow(10,FraLength);
for(uint8_t i=0; i<FraLength; i++)
{
tempNum = tempNum*type;
temp = tempNum/Pow(10,FraLength);
tempNum = tempNum-tempNum/Pow(10,FraLength)*Pow(10,FraLength);
if(temp > 9)
state = Serial_SendByte(USARTx, temp-10+'A');
else
state = Serial_SendByte(USARTx, temp+'0');
if(state == 0)
return 0;
}
return 1;
}
/**
* @摘要 这是一个可变参数函数,用于格式化发送字符串
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 format:字符串
* @参数 ...:可变参数
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_Printf(USART_TypeDef* USARTx, char* format,...)
{
uint8_t state = 0;
char str[100];
va_list arg;
va_start(arg,format);
vsprintf(str,format,arg);
va_end(arg);
state = Serial_SendString(USART1,str);
if(state == 0)
return 0;
return 1;
}
/**
* @摘要 串口发送中文字符串(或一个字符)
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 Chinese:要发送的中文字符串
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendChinese(USART_TypeDef* USARTx, char *Chinese)
{
uint8_t state = 0;
uint8_t cnt = 0, pChinese = 0, SingleChinese[4] = {0};
uint8_t index;
for(uint8_t i=0; Chinese[i]!='\0'; i++)
{
SingleChinese[pChinese] = Chinese[i];
pChinese++;
if(pChinese>=Serial_CHN_CHAR_WIDTH)
{
pChinese = 0;
cnt++;
for(index=0; strcmp(Serial_Chinese[index].Index, "") != 0; index++)
{
if(strcmp(Serial_Chinese[index].Index, (const char*)SingleChinese) == 0)
break;
}
state = Serial_SendArray(USARTx, (uint8_t *)Serial_Chinese[index].Data, 3);
if(state == 0)
return 0;
}
}
return 1;
}
/**
* @摘要 串口发送数据包
* @参数 USARTx:串口号,x可以为1、2、3...(根据具体芯片型号选择)
* @参数 package:要发送的数据包
* @返回值 0或1:0代表发送失败,1代表发送成功
* @说明 无
*/
uint8_t Serial_SendPackage(USART_TypeDef* USARTx, uint8_t* package)
{
uint8_t state = 0;
state = Serial_SendByte(USART1,'@'); //包头
if(state == 0)
return 0;
state = Serial_SendArray(USART1, package, 4); //数据
if(state == 0)
return 0;
state = Serial_SendString(USART1, "\r\n"); //包尾
if(state == 0)
return 0;
return 1;
}
/**
* @摘要 获取接收数据大小
* @参数 无
* @返回值 接收数据个数
* @说明 无
*/
uint16_t Serial_GetRxSize(void)
{
return RxSize;
}
/**
* @摘要 获取接收标志位
* @参数 无
* @返回值 接收标志:1(完成接收),0(未完成接收或未接收)
* @说明 无
*/
uint8_t Serial_GetRxFlag(void)
{
return RxFlag1;
}
/**
* @摘要 清除接收标志位
* @参数 无
* @返回值 无
* @说明 无
*/
void Serial_ClearRxFlag(void)
{
RxFlag1 = 0;
}
/**
* @摘要 获取接收数据
* @参数 Rxdata:指向存储接收数据地址的指针
* @返回值 接收到的数据包的指针
* @说明 调用此函数会自动清除接收缓冲区
*/
void Serial_GetRxData(uint8_t* Rxdata)
{
for(uint8_t i=0; i<100; i++)
{
if(RxBuff1[i] == 0)
break;
Rxdata[i] = RxBuff1[i];
RxBuff1[i] = 0;
}
}
/**
* @摘要 USART1中断服务函数
* @参数 无
* @返回值 无
* @说明 无
*/
void USART1_IRQHandler(void)
{
static uint16_t RxIndex = 0;
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
//USART_ClearITPendingBit(USART1, USART_IT_RXNE);
if(RxIndex < Serial_Buffer_Size)
{
RxBuff1[RxIndex] = USART_ReceiveData(USART1);
RxIndex++;
}
}
if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)
{
USART_ReceiveData(USART1);
RxSize = RxIndex;
RxIndex = 0;
RxFlag1 = 1;
}
}
- Serial.h文件内容如下
#ifndef __SERIAL_H
#define __SERIAL_H
#include <String.h>
#include <stdarg.h>
#include <stdio.h>
#include "stm32f4xx.h" // Device header
#include "Serial_Data.h"
#include "MyMath.h"
void Serial_Init(void);
uint8_t Serial_SendByte(USART_TypeDef* USARTx, uint8_t Byte);
uint8_t Serial_SendArray(USART_TypeDef* USARTx, uint8_t *array, uint16_t length);
uint8_t Serial_SendString(USART_TypeDef* USARTx, const char *str);
uint8_t Serial_SendNum(USART_TypeDef* USARTx, uint32_t Number, uint8_t type, uint8_t length);
uint8_t Serial_SendSignedNum(USART_TypeDef* USARTx, int32_t Number, uint8_t length,FunctionalState ShowSign);
uint8_t Serial_SendFloatNum(USART_TypeDef* USARTx, double Number,uint8_t type, uint8_t IntLength, uint8_t FraLength);
uint8_t Serial_SendChinese(USART_TypeDef* USARTx, char *Chinese);
uint8_t Serial_Printf(USART_TypeDef* USARTx, char* format,...);
uint8_t Serial_SendPackage(USART_TypeDef* USARTx, uint8_t* package);
uint8_t Serial_GetRxFlag(void);
void Serial_ClearRxFlag(void);
void Serial_GetRxData(uint8_t* Rxdata);
#endif