代码在型号为STM32F103VET6测试验证通过
以下为所有代码
串口1工程包含的代码文件有如下几个文件
timer2.h
#ifndef _TIMER2_H
#define _TIMER2_H
#include "config.h"
void TIM2Init(u16 period, u16 prescaler);//中断处理函数放在stm32f10x_it.c文件
#endif
timer2.c
#include "timer2.h"
/* TIM2中断优先级配置函数, */
void NVIC_TIM2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = TIM2_IRQn; //选择TIM2中断通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //设定抢占优先级为0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //设定响应优先级为0
NVIC_Init(&NVIC_initstructure);
}
/* 定时器2初始化函数,period-计数周期,Prescaler-预分频值 */
void TIM2Init(u16 period, u16 prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = period-1; //设定自动重装载计数值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //设定预分频系数 计数时钟=定时器时钟/(分频系数+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //基本定时器没有时钟分频功能,此项会被忽略
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式 基本定时器只有向上
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2
NVIC_TIM2Enable(); //初始化TIM2中断优先级
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位,否则启动中断会先进中断服务函数
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2中断
TIM_Cmd(TIM2, ENABLE); //使能TIM2定时器
}
uart1.h
#ifndef _UART1_H
#define _UART1_H
#include "config.h"
#define BAUD1 9600//波特率宏定义
void USART1Init(u32 baud);//初始化串口和配置波特率
#endif
uart1.c
#include "uart1.h"
/* USART1引脚初始化 */
void USART1_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TXD引脚-PA9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //TXD设置为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速率50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //RXD引脚-PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/* USART1中断优先级初始化 */
void NVIC_USART1Enable(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //选择USART1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
}
/* USART1模块初始化函数, baud-波特率 */
void USART1Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
USART1_IOInit(); //USART1引脚初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟,USART时钟在AP2上,其它4个串口在AP1上
USART_InitStructure.USART_BaudRate = baud; //设置波特率为baud
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置为8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置为1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //禁用硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; //选择USART发送和接收模式
USART_Init(USART1, &USART_InitStructure); //初始化USART1
NVIC_USART1Enable(); //USART1中断优先级初始化
USART_ITConfig(USART1,USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(USART1,ENABLE); //使能USART11
}
uart1_handle.h
#ifndef _UART1_HANDLE_H
#define _UART1_HANDLE_H
#include"config.h"
#define JIANGE_TIME1 30//帧间隔时间宏定义
void UartWrite1(unsigned char *buf, unsigned char len);//串口数据写入,即串口发送函数
unsigned char UartRead1(unsigned char *buf, unsigned char len);//串口数据读取函数
void UartRxMonitor1(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void UartAction1(unsigned char *buf, unsigned char len);//串口动作函数,根据接收到的命令帧执行响应的动作
void UartDriver1(void);//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartSendByte1(void);/* 从串口发送一字节数据,需在串口发送中断中调用 */
extern unsigned char cntRxd1; //接收字节计数器
extern unsigned char bufRxd1[60]; //接收字节缓冲区
#endif
uart1_handle.c
#include "uart1_handle.h"
unsigned char flagFrame1=0;
unsigned char cntRxd1 = 0; //接收字节计数器
unsigned char bufRxd1[60]; //接收字节缓冲区
unsigned char bufTxd1[60]; //数据发送缓冲区
int bufTxdPosition1 = 0; //缓冲区发送数据的最后位置
int bufWritePosition1 = 0; //向缓冲区写入数据的最后位置
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite1(unsigned char *buf, unsigned char len)
{
while (len--) //循环发送所有字节
{
bufTxd1[bufWritePosition1] = *buf++;//待发送数据逐一复制到发送缓冲区
bufWritePosition1++;//向缓冲区写入数据的最后位置
}
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //开启发送中断发送数据
}
void UartSendByte1(void)/* 从串口发送一字节数据,需在串口发送中断中调用 */
{
if (bufTxdPosition1 != bufWritePosition1) //最后发送位置与写入位置不等,说明还有需要发送的数据
{
USART_SendData(USART1, bufTxd1[bufTxdPosition1]); //发出最后位置上的数据
bufTxdPosition1++; //至缓冲区结尾时归零
}
else //最后发送位置与写入位置相等,说明写入的数据已发送完
{
bufTxdPosition1=0;
bufWritePosition1=0;
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //关闭发送中断,终止本次发送
}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead1(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd1) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd1;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd1[i];
}
cntRxd1 = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartRxMonitor1(unsigned char ms)/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd1 > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd1) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd1;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < JIANGE_TIME1) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= JIANGE_TIME1) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame1 = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction1(unsigned char *buf, unsigned char len)
{
UartWrite1(buf,len);
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver1()
{
unsigned char len;
unsigned char buf[60];
if (flagFrame1) //有命令到达时,读取处理该命令
{
flagFrame1 = 0;
len = UartRead1(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中
UartAction1(buf, len); //传递数据帧,调用动作执行函数
}
}
stm32f10x_it.c
#include "stm32f10x_it.h"
#include "uart1_handle.h"
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_FLAG_Update) == SET) //检测是否为定时器溢出中断
{
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志位
UartRxMonitor1(1);/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
}
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //检测接收中断标志位
{
if (cntRxd1 < sizeof(bufRxd1)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd1[cntRxd1++] =USART_ReceiveData(USART1); //读取接收到的数据
}
}
if(USART_GetITStatus(USART1, USART_IT_TXE) == SET) //检测发送中断标志位
{
UartSendByte1();
}
}
main.c
#include "timer2.h"
#include "uart1.h"
#include "uart1_handle.h"
int main(void)
{
TIM2Init(10, 7200);//配置定时器定时1MS
USART1Init(BAUD1);//初始化串口和配置波特率
while (1)
{
UartDriver1();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
}
}
串口2工程包含的代码文件有如下几个文件
timer2.h
#ifndef _TIMER2_H
#define _TIMER2_H
#include "config.h"
void TIM2Init(u16 period, u16 prescaler);//中断处理函数放在stm32f10x_it.c文件
#endif
timer2.c
#include "timer2.h"
/* TIM2中断优先级配置函数, */
void NVIC_TIM2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = TIM2_IRQn; //选择TIM2中断通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //设定抢占优先级为0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //设定响应优先级为0
NVIC_Init(&NVIC_initstructure);
}
/* 定时器2初始化函数,period-计数周期,Prescaler-预分频值 */
void TIM2Init(u16 period, u16 prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = period-1; //设定自动重装载计数值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //设定预分频系数 计数时钟=定时器时钟/(分频系数+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //基本定时器没有时钟分频功能,此项会被忽略
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式 基本定时器只有向上
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2
NVIC_TIM2Enable(); //初始化TIM2中断优先级
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位,否则启动中断会先进中断服务函数
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2中断
TIM_Cmd(TIM2, ENABLE); //使能TIM2定时器
}
uart2.h
#ifndef _UART2_H
#define _UART2_H
#include "config.h"
#define BAUD2 9600 //波特率宏定义
void USART2Init(u32 baud);//初始化串口2和配置波特率
#endif
uart2.c
#include "uart2.h"
/* USART2引脚初始化 */
void USART2_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //TXD引脚-PA2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //TXD设置为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速率50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //RXD引脚-PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //RXD上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/* USART2中断优先级初始化 */
void NVIC_USART2Enable(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //选择USART2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
}
/* USART2模块初始化函数, baud-波特率 */
void USART2Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
USART2_IOInit(); //USART2引脚初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART2时钟
USART_InitStructure.USART_BaudRate = baud; //设置波特率为baud
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置为8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置为1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //禁用硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; //选择USART发送和接收模式
USART_Init(USART2, &USART_InitStructure); //初始化USART2
NVIC_USART2Enable(); //USART2中断优先级初始化
USART_ITConfig(USART2,USART_IT_RXNE, ENABLE); //开启串口2接受中断
USART_Cmd(USART2,ENABLE); //使能USART2
}
uart2_handle.h
#ifndef _UART2_HANDLE_H
#define _UART2_HANDLE_H
#include"config.h"
#define JIANGE_TIME2 30//帧间隔时间宏定义
unsigned char UartRead2(unsigned char *buf, unsigned char len);//串口数据读取函数
void UartRxMonitor2(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void UartAction2(unsigned char *buf, unsigned char len);//串口动作函数,根据接收到的命令帧执行响应的动作
void UartDriver2(void);//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartSendByte2(void);/* 从串口发送一字节数据,需在串口发送中断中调用 */
void UartWrite2(unsigned char *buf, unsigned char len);
extern unsigned char cntRxd2; //接收字节计数器
extern unsigned char bufRxd2[60]; //接收字节缓冲区
#endif
uart2_handle.c
#include "uart2_handle.h"
unsigned char flagFrame2 = 0; //帧接收完成标志,即接收到一帧新数据
unsigned char cntRxd2 = 0; //接收字节计数器
unsigned char bufRxd2[60]; //接收字节缓冲区
unsigned char bufTxd2[60]; //数据发送缓冲区
int bufTxdPosition2 = 0; //缓冲区发送数据的最后位置
int bufWritePosition2 = 0; //向缓冲区写入数据的最后位置
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite2(unsigned char *buf, unsigned char len)
{
while (len--) //循环发送所有字节
{
bufTxd2[bufWritePosition2] = *buf++;//待发送数据逐一复制到发送缓冲区
bufWritePosition2++;//向缓冲区写入数据的最后位置
}
USART_ITConfig(USART2, USART_IT_TXE, ENABLE); //开启发送中断发送数据
}
void UartSendByte2(void)/* 从串口发送一字节数据,需在串口发送中断中调用 */
{
if (bufTxdPosition2 != bufWritePosition2) //最后发送位置与写入位置不等,说明还有需要发送的数据
{
USART_SendData(USART2, bufTxd2[bufTxdPosition2]); //发出最后位置上的数据
bufTxdPosition2++; //至缓冲区结尾时归零
}
else //最后发送位置与写入位置相等,说明写入的数据已发送完
{
bufTxdPosition2=0;
bufWritePosition2=0;
USART_ITConfig(USART2, USART_IT_TXE, DISABLE); //关闭发送中断,终止本次发送
}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead2(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd2) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd2;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd2[i];
}
cntRxd2 = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartRxMonitor2(unsigned char ms)/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd2 > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd2) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd2;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < JIANGE_TIME2) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= JIANGE_TIME2) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame2 = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction2(unsigned char *buf, unsigned char len)
{
UartWrite2(buf,len);
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver2()
{
unsigned char len;
unsigned char buf[30];
if (flagFrame2) //有命令到达时,读取处理该命令
{
flagFrame2 = 0;
len = UartRead2(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中
UartAction2(buf, len); //传递数据帧,调用动作执行函数
}
}
stm32f10x_it.c
#include "stm32f10x_it.h"
#include "uart2_handle.h"
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_FLAG_Update) == SET) //检测是否为定时器溢出中断
{
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志位
UartRxMonitor2(1);/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
}
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET) //检测接收中断标志位
{
if (cntRxd2 < sizeof(bufRxd2)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd2[cntRxd2++] =USART_ReceiveData(USART2); //读取接收到的数据
}
}
if(USART_GetITStatus(USART2, USART_IT_TXE) == SET) //检测发送中断标志位
{
UartSendByte2();
}
}
main.c
#include "uart2.h"
#include "uart2_handle.h"
#include "timer2.h"
int main(void)
{
USART2Init(BAUD2);//初始化串口和配置波特率
TIM2Init(10, 7200);//配置定时器配置1MS
while (1)
{
UartDriver2();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
}
}
串口3工程包含的代码文件有如下几个文件
timer2.h
#ifndef _TIMER2_H
#define _TIMER2_H
#include "config.h"
void TIM2Init(u16 period, u16 prescaler);//中断处理函数放在stm32f10x_it.c文件
#endif
timer2.c
#include "timer2.h"
/* TIM2中断优先级配置函数, */
void NVIC_TIM2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = TIM2_IRQn; //选择TIM2中断通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //设定抢占优先级为0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //设定响应优先级为0
NVIC_Init(&NVIC_initstructure);
}
/* 定时器2初始化函数,period-计数周期,Prescaler-预分频值 */
void TIM2Init(u16 period, u16 prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = period-1; //设定自动重装载计数值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //设定预分频系数 计数时钟=定时器时钟/(分频系数+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //基本定时器没有时钟分频功能,此项会被忽略
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式 基本定时器只有向上
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2
NVIC_TIM2Enable(); //初始化TIM2中断优先级
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位,否则启动中断会先进中断服务函数
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2中断
TIM_Cmd(TIM2, ENABLE); //使能TIM2定时器
}
uart3.h
#ifndef _UART3_H
#define _UART3_H
#include "config.h"
#define BAUD3 9600 //波特率宏定义
void USART3Init(u32 baud);//初始化串口和配置波特率
#endif
uart3.c
#include "uart3.h"
void USART3_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void NVIC_USART3Enable(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //
NVIC_Init(&NVIC_InitStructure);
}
void USART3Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
USART3_IOInit();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART3, &USART_InitStructure);
NVIC_USART3Enable();
USART_ITConfig(USART3,USART_IT_RXNE, ENABLE);
USART_Cmd(USART3,ENABLE);
}
uart3_handle.h
#ifndef _UART3_HANDLE_H
#define _UART3_HANDLE_H
#include"config.h"
#define JIANGE_TIME3 30 //帧间隔时间宏定义
void UartWrite3(unsigned char *buf, unsigned char len);//串口数据写入,即串口发送函数
unsigned char UartRead3(unsigned char *buf, unsigned char len);//串口数据读取函数
void UartRxMonitor3(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void UartAction3(unsigned char *buf, unsigned char len);//串口动作函数,根据接收到的命令帧执行响应的动作
void UartDriver3(void);//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartSendByte3(void);/* 从串口发送一字节数据,需在串口发送中断中调用 */
extern unsigned char cntRxd3; //接收字节计数器
extern unsigned char bufRxd3[60]; //接收字节缓冲区
#endif
uart3_handle.c
#include "uart3_handle.h"
unsigned char flagFrame3=0;
unsigned char cntRxd3 = 0; //接收字节计数器
unsigned char bufRxd3[60]={0}; //接收字节缓冲区
unsigned char bufTxd3[60]={0}; //数据发送缓冲区
int bufTxdPosition3 = 0; //缓冲区发送数据的最后位置
int bufWritePosition3 = 0; //向缓冲区写入数据的最后位置
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite3(unsigned char *buf, unsigned char len)
{
while (len--) //循环发送所有字节
{
bufTxd3[bufWritePosition3] = *buf++;//待发送数据逐一复制到发送缓冲区
bufWritePosition3++;//向缓冲区写入数据的最后位置
}
USART_ITConfig(USART3, USART_IT_TXE, ENABLE); //开启发送中断发送数据
}
void UartSendByte3(void)/* 从串口发送一字节数据,需在串口发送中断中调用 */
{
if (bufTxdPosition3 != bufWritePosition3) //最后发送位置与写入位置不等,说明还有需要发送的数据
{
USART_SendData(USART3, bufTxd3[bufTxdPosition3]); //发出最后位置上的数据
bufTxdPosition3++; //至缓冲区结尾时归零
}
else //最后发送位置与写入位置相等,说明写入的数据已发送完
{
bufTxdPosition3=0;
bufWritePosition3=0;
USART_ITConfig(USART3, USART_IT_TXE, DISABLE); //关闭发送中断,终止本次发送
}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead3(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd3) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd3;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd3[i];
}
cntRxd3 = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartRxMonitor3(unsigned char ms)/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd3 > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd3) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd3;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < JIANGE_TIME3) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= JIANGE_TIME3) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame3 = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction3(unsigned char *buf, unsigned char len)
{
UartWrite3(buf,len);
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver3()
{
unsigned char len;
unsigned char buf[60];
if (flagFrame3) //有命令到达时,读取处理该命令
{
flagFrame3 = 0;
len = UartRead3(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中
UartAction3(buf, len); //传递数据帧,调用动作执行函数
}
}
stm32f10x_it.c
#include "stm32f10x_it.h"
#include "uart3_handle.h"
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_FLAG_Update) == SET) //检测是否为定时器溢出中断
{
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志位
UartRxMonitor3(1);/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
}
}
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3,USART_IT_RXNE) == SET) //检测接收中断标志位
{
if (cntRxd3 < sizeof(bufRxd3)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd3[cntRxd3++] =USART_ReceiveData(USART3); //读取接收到的数据
}
}
if(USART_GetITStatus(USART3, USART_IT_TXE) == SET) //检测发送中断标志位
{
UartSendByte3();
}
}
main.c
#include "uart3.h"
#include "uart3_handle.h"
#include "timer2.h"
int main(void)
{
USART3Init(BAUD3);//初始化串口和配置波特率
TIM2Init(10, 7200);
while (1)
{
UartDriver3();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
}
}
串口4工程包含的代码文件有如下几个文件
timer2.h
#ifndef _TIMER2_H
#define _TIMER2_H
#include "config.h"
void TIM2Init(u16 period, u16 prescaler);//中断处理函数放在stm32f10x_it.c文件
#endif
timer2.c
#include "timer2.h"
/* TIM2中断优先级配置函数, */
void NVIC_TIM2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = TIM2_IRQn; //选择TIM2中断通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //设定抢占优先级为0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //设定响应优先级为0
NVIC_Init(&NVIC_initstructure);
}
/* 定时器2初始化函数,period-计数周期,Prescaler-预分频值 */
void TIM2Init(u16 period, u16 prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = period-1; //设定自动重装载计数值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //设定预分频系数 计数时钟=定时器时钟/(分频系数+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //基本定时器没有时钟分频功能,此项会被忽略
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式 基本定时器只有向上
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2
NVIC_TIM2Enable(); //初始化TIM2中断优先级
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位,否则启动中断会先进中断服务函数
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2中断
TIM_Cmd(TIM2, ENABLE); //使能TIM2定时器
}
uart4.h
#ifndef _UART4_H
#define _UART4_H
#include "config.h"
#define BAUD4 9600 //波特率宏定义
void UART4Init(u32 baud);//初始化串口和配置波特率
#endif
uart4.c
#include "uart4.h"
/* UART4引脚初始化 */
void UART4_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能GPIOC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TXD引脚-C10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //TXD设置为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速率50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //RXD引脚-C11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //RXD浮空输入
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/* UART4中断优先级初始化 */
void NVIC_UART4Enable(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; //选择UART4中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
}
/* UART4模块初始化函数, baud-波特率 */
void UART4Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
UART4_IOInit(); //UART4引脚初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); //使能时钟,USART1时钟在AP2上,其它4个串口在AP1上
USART_InitStructure.USART_BaudRate = baud; //设置波特率为baud
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置为8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置为1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //禁用硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; //选择UART发送和接收模式
USART_Init(UART4, &USART_InitStructure); //初始化UART4
NVIC_UART4Enable(); //UART4中断优先级初始化
USART_ITConfig(UART4,USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(UART4,ENABLE); //UART4
}
uart4_handle.h
#ifndef _UART4_HANDLE_H
#define _UART4_HANDLE_H
#include"config.h"
#define JIANGE_TIME4 30 //帧间隔时间宏定义
void UartWrite4(unsigned char *buf, unsigned char len);//串口数据写入,即串口发送函数
unsigned char UartRead4(unsigned char *buf, unsigned char len);//串口数据读取函数
void UartRxMonitor4(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void UartAction4(unsigned char *buf, unsigned char len);//串口动作函数,根据接收到的命令帧执行响应的动作
void UartDriver4(void);//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartSendByte4(void);/* 从串口发送一字节数据,需在串口发送中断中调用 */
extern unsigned char cntRxd4; //接收字节计数器
extern unsigned char bufRxd4[60]; //接收字节缓冲区
#endif
uart4_handle.c
#include "uart4_handle.h"
unsigned char flagFrame4=0;
unsigned char cntRxd4 = 0; //接收字节计数器
unsigned char bufRxd4[60]={0}; //接收字节缓冲区
unsigned char bufTxd4[60]={0}; //数据发送缓冲区
int bufTxdPosition4 = 0; //缓冲区发送数据的最后位置
int bufWritePosition4 = 0; //向缓冲区写入数据的最后位置
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite4(unsigned char *buf, unsigned char len)
{
while (len--) //循环发送所有字节
{
bufTxd4[bufWritePosition4] = *buf++;//待发送数据逐一复制到发送缓冲区
bufWritePosition4++;//向缓冲区写入数据的最后位置
}
USART_ITConfig(UART4, USART_IT_TXE, ENABLE); //开启发送中断发送数据
}
void UartSendByte4(void)/* 从串口发送一字节数据,需在串口发送中断中调用 */
{
if (bufTxdPosition4 != bufWritePosition4) //最后发送位置与写入位置不等,说明还有需要发送的数据
{
USART_SendData(UART4, bufTxd4[bufTxdPosition4]); //发出最后位置上的数据
bufTxdPosition4++; //至缓冲区结尾时归零
}
else //最后发送位置与写入位置相等,说明写入的数据已发送完
{
bufTxdPosition4=0;
bufWritePosition4=0;
USART_ITConfig(UART4, USART_IT_TXE, DISABLE); //关闭发送中断,终止本次发送
}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead4(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd4) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd4;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd4[i];
}
cntRxd4 = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartRxMonitor4(unsigned char ms)/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd4 > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd4) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd4;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < JIANGE_TIME4) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= JIANGE_TIME4) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame4 = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction4(unsigned char *buf, unsigned char len)
{
UartWrite4(buf,len);
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver4()
{
unsigned char len;
unsigned char buf[60];
if (flagFrame4) //有命令到达时,读取处理该命令
{
flagFrame4 = 0;
len = UartRead4(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中
UartAction4(buf, len); //传递数据帧,调用动作执行函数
}
}
stm32f10x_it.c
#include "stm32f10x_it.h"
#include "uart4_handle.h"
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_FLAG_Update) == SET) //检测是否为定时器溢出中断
{
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志位
UartRxMonitor4(1);/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
}
}
void UART4_IRQHandler(void)
{
if(USART_GetITStatus(UART4,USART_IT_RXNE) == SET) //检测接收中断标志位
{
if (cntRxd4 < sizeof(bufRxd4)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd4[cntRxd4++] =USART_ReceiveData(UART4); //读取接收到的数据
}
}
if(USART_GetITStatus(UART4, USART_IT_TXE) == SET) //检测发送中断标志位
{
UartSendByte4();
}
}
main.c
#include "uart4.h"
#include "uart4_handle.h"
#include "timer2.h"
int main(void)
{
UART4Init(BAUD4);//初始化串口和配置波特率
TIM2Init(10, 7200);//配置定时器定时1MS
while (1)
{
UartDriver4();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
}
}
串口5工程包含的代码文件有如下几个文件
timer2.h
#ifndef _TIMER2_H
#define _TIMER2_H
#include "config.h"
void TIM2Init(u16 period, u16 prescaler);//中断处理函数放在stm32f10x_it.c文件
#endif
timer2.c
#include "timer2.h"
/* TIM2中断优先级配置函数, */
void NVIC_TIM2Enable(void)
{
NVIC_InitTypeDef NVIC_initstructure;
NVIC_initstructure.NVIC_IRQChannel = TIM2_IRQn; //选择TIM2中断通道
NVIC_initstructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_initstructure.NVIC_IRQChannelPreemptionPriority = 0; //设定抢占优先级为0
NVIC_initstructure.NVIC_IRQChannelSubPriority = 0; //设定响应优先级为0
NVIC_Init(&NVIC_initstructure);
}
/* 定时器2初始化函数,period-计数周期,Prescaler-预分频值 */
void TIM2Init(u16 period, u16 prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
TIM_TimeBaseStructure.TIM_Period = period-1; //设定自动重装载计数值
TIM_TimeBaseStructure.TIM_Prescaler = prescaler-1; //设定预分频系数 计数时钟=定时器时钟/(分频系数+1)
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //基本定时器没有时钟分频功能,此项会被忽略
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式 基本定时器只有向上
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2
NVIC_TIM2Enable(); //初始化TIM2中断优先级
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位,否则启动中断会先进中断服务函数
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2中断
TIM_Cmd(TIM2, ENABLE); //使能TIM2定时器
}
uart5.h
#ifndef _UART5_H
#define _UART5_H
#include "config.h"
#define BAUD5 9600 //波特率宏定义
void UART5Init(u32 baud);//初始化串口和配置波特率
#endif
uart5.c
#include "uart5.h"
/* UART5引脚初始化 */
void UART5_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //TXD引脚-C12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //TXD设置为复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速率50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //RXD引脚-D2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //RXD浮空输入
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/* UART5中断优先级初始化 */
void NVIC_UART5Enable(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; //选择USART5中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
}
/* UART5模块初始化函数, baud-波特率 */
void UART5Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
UART5_IOInit(); //UART5引脚初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); //使能时钟,USART1时钟在AP2上,其它4个串口在AP1上
USART_InitStructure.USART_BaudRate = baud; //设置波特率为baud
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置为8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置为1位停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //禁用硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; //选择USART发送和接收模式
USART_Init(UART5, &USART_InitStructure); //初始化UART5
NVIC_UART5Enable(); //UART5中断优先级初始化
USART_ITConfig(UART5,USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(UART5,ENABLE); //使能UART5
}
uart5_handle.h
#ifndef _UART5_HANDLE_H
#define _UART5_HANDLE_H
#include"config.h"
#define JIANGE_TIME5 30//帧间隔时间宏定义
void UartWrite5(unsigned char *buf, unsigned char len);//串口数据写入,即串口发送函数
unsigned char UartRead5(unsigned char *buf, unsigned char len);//串口数据读取函数
void UartRxMonitor5(unsigned char ms);//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
void UartAction5(unsigned char *buf, unsigned char len);//串口动作函数,根据接收到的命令帧执行响应的动作
void UartDriver5(void);//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
void UartSendByte5(void);/* 从串口发送一字节数据,需在串口发送中断中调用 */
extern unsigned char cntRxd5; //接收字节计数器
extern unsigned char bufRxd5[60]; //接收字节缓冲区
#endif
uart5_handle.c
#include "uart5_handle.h"
unsigned char flagFrame5=0;
unsigned char cntRxd5 = 0; //接收字节计数器
unsigned char bufRxd5[60]={0}; //接收字节缓冲区
unsigned char bufTxd5[60]={0}; //数据发送缓冲区
int bufTxdPosition5 = 0; //缓冲区发送数据的最后位置
int bufWritePosition5 = 0; //向缓冲区写入数据的最后位置
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite5(unsigned char *buf, unsigned char len)
{
while (len--) //循环发送所有字节
{
bufTxd5[bufWritePosition5] = *buf++;//待发送数据逐一复制到发送缓冲区
bufWritePosition5++;//向缓冲区写入数据的最后位置
}
USART_ITConfig(UART5, USART_IT_TXE, ENABLE); //开启发送中断发送数据
}
void UartSendByte5(void)/* 从串口发送一字节数据,需在串口发送中断中调用 */
{
if (bufTxdPosition5 != bufWritePosition5) //最后发送位置与写入位置不等,说明还有需要发送的数据
{
USART_SendData(UART5, bufTxd5[bufTxdPosition5]); //发出最后位置上的数据
bufTxdPosition5++; //至缓冲区结尾时归零
}
else //最后发送位置与写入位置相等,说明写入的数据已发送完
{
bufTxdPosition5=0;
bufWritePosition5=0;
USART_ITConfig(UART5, USART_IT_TXE, DISABLE); //关闭发送中断,终止本次发送
}
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead5(unsigned char *buf, unsigned char len)
{
unsigned char i;
if (len > cntRxd5) //指定读取长度大于实际接收到的数据长度时,
{ //读取长度设置为实际接收到的数据长度
len = cntRxd5;
}
for (i=0; i<len; i++) //拷贝接收到的数据到接收指针上
{
*buf++ = bufRxd5[i];
}
cntRxd5 = 0; //接收计数器清零
return len; //返回实际读取长度
}
void UartRxMonitor5(unsigned char ms)/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
{
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd5 > 0) //接收计数器大于零时,监控总线空闲时间
{
if (cntbkp != cntRxd5) //接收计数器改变,即刚接收到数据时,清零空闲计时
{
cntbkp = cntRxd5;
idletmr = 0;
}
else //接收计数器未改变,即总线空闲时,累积空闲时间
{
if (idletmr < JIANGE_TIME5) //空闲计时小于30ms时,持续累加
{
idletmr += ms;
if (idletmr >= JIANGE_TIME5) //空闲时间达到30ms时,即判定为一帧接收完毕
{
flagFrame5 = 1; //设置帧接收完成标志
}
}
}
}
else
{
cntbkp = 0;
}
}
/* 串口动作函数,根据接收到的命令帧执行响应的动作
buf-接收到的命令帧指针,len-命令帧长度 */
void UartAction5(unsigned char *buf, unsigned char len)
{
UartWrite5(buf,len);
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver5()
{
unsigned char len;
unsigned char buf[60];
if (flagFrame5) //有命令到达时,读取处理该命令
{
flagFrame5 = 0;
len = UartRead5(buf, sizeof(buf)); //将接收到的命令读取到缓冲区中
UartAction5(buf, len); //传递数据帧,调用动作执行函数
}
}
stm32f10x_it.c
#include "stm32f10x_it.h"
#include "uart5_handle.h"
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_FLAG_Update) == SET) //检测是否为定时器溢出中断
{
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除中断标志位
UartRxMonitor5(1);/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
}
}
void UART5_IRQHandler(void)
{
if(USART_GetITStatus(UART5,USART_IT_RXNE) == SET) //检测接收中断标志位
{
if (cntRxd5 < sizeof(bufRxd5)) //接收缓冲区尚未用完时,
{ //保存接收字节,并递增计数器
bufRxd5[cntRxd5++] =USART_ReceiveData(UART5); //读取接收到的数据
}
}
if(USART_GetITStatus(UART5, USART_IT_TXE) == SET) //检测发送中断标志位
{
UartSendByte5();
}
}
main.c
#include "uart5.h"
#include "uart5_handle.h"
#include "timer2.h"
int main(void)
{
UART5Init(BAUD5);//初始化串口和配置波特率
TIM2Init(10, 7200);
while (1)
{
UartDriver5();//串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用
}
}