在编写STM32代码的时候,我们常常需要繁琐的在.c文件中寻找需要改动的语句,这种改动方法不仅繁琐,而且有较大的出错可能。在准备电赛期间,发现网上有人采用对.h文件改动而直接配置.c文件,相较于直接改动.c文件,更加方便且更不容易出错。所以我对于部分STM32的代码,基于正点原子的例程,进行了一些改动。
? ? ? ? 下面列出部分.h代码供大家参考,技术含量并不是太高,见谅。
? 串口代码:
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
/***************************
串口封装程序(DUMJ)
创建
时间:2021/07/30
完成人:DUMJ
***************************/
/*********************************************************************
接线方式:
串口 TX RX
USART1 A9 A10
USART2 A2 A3
USART3 B10 B11
UART4 C10 C11
UART5 C12 D2
注意: 若要使用printf函数,则每次更改串口时,需要改变或增加fputs函数
使用printf函数,发送时无需加\r\n
********************************************************************/
/******************************************************************************
若要使用多个串口,无法使用printf时,将以下代码直接复制
到所需要的地方,此代码功能:将接收到的数据发送出去;
if(USART2_RX_STA&0x8000)
{
len=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART2, USART_RX_BUF[t]);//向串口1发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART2_RX_STA=0;
}
注:如果使用的是串口4、5,请将USARTx_RX_STA格式改为UARTx_RX_STA
*****************************************************************************/
#define USART_ON 1
#define USART_OFF 0
/************************************************/
/***开启---USART_ON***/ /***关闭---USART_OFF***/
#define USART1_switch USART_ON //默认开启
#define USART2_switch USART_OFF //默认关闭
#define USART3_switch USART_OFF //默认关闭
#define UART4_switch USART_OFF //默认关闭
#define UART5_switch USART_OFF //默认关闭
/*** 波特率设置:默认为115200 ***/
#define DEBUG_USART1_BAUDRATE 115200 //若使用蓝牙,请注意两者一致
#define DEBUG_USART2_BAUDRATE 115200 //若使用蓝牙,请注意两者一致
#define DEBUG_USART3_BAUDRATE 115200 //若使用蓝牙,请注意两者一致
#define DEBUG_UART4_BAUDRATE 115200 //若使用蓝牙,请注意两者一致
#define DEBUG_UART5_BAUDRATE 115200 //若使用蓝牙,请注意两者一致
#define USART_REC_LEN 200 //定义最大接收字节数 200
extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART1_RX_STA; //串口一接收状态标记
extern u16 USART2_RX_STA; //串口二接收状态标记
extern u16 USART3_RX_STA; //串口三接收状态标记
extern u16 UART4_RX_STA; //串口四接收状态标记
extern u16 UART5_RX_STA; //串口五接收状态标记
//如果想串口中断接收,请不要注释以下宏定义
void Usart_1_init(void); //串口一初始化
void Usart_2_init(void); //串口二初始化
void Usart_3_init(void); //串口三初始化
void Uart_4_init(void); //串口四初始化
void Uart_5_init(void); //串口五初始化
#endif
#include "sys.h"
#include "usart.h"
//
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h" //ucos 使用
#endif
//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
/*使用microLib的方法*/
/*
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
return ch;
}
int GetKey (void) {
while (!(USART1->SR & USART_FLAG_RXNE));
return ((int)(USART1->DR & 0x1FF));
}
*/
//接收状态标记
u16 USART1_RX_STA=0; //串口一接收状态标记
u16 USART2_RX_STA=0; //串口二接收状态标记
u16 USART3_RX_STA=0; //串口三接收状态标记
u16 UART4_RX_STA=0; //串口四接收状态标记
u16 UART5_RX_STA=0; //串口五接收状态标记
/****************
串口一初始化程序
****************/
#if USART1_switch //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
void Usart_1_init(void)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = DEBUG_USART1_BAUDRATE; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC);
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
USART_RX_BUF[USART1_RX_STA&0X3FFF]=Res;
USART1_RX_STA++;
printf("%c",Res);
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
#endif
/****************
串口二初始化程序
****************/
#if USART2_switch //如果使能了接收
//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
void Usart_2_init(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART2,GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//USART2_TX GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.2
//USART2_RX GPIOA.3初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.3
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART2 初始化设置
USART_InitStructure.USART_BaudRate = DEBUG_USART2_BAUDRATE; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART2, ENABLE); //使能串口2
USART_ClearFlag(USART2, USART_FLAG_TC);
}
void USART2_IRQHandler(void) //串口2中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART2); //读取接收到的数据
if((USART2_RX_STA&0x8000)==0) //接收未完成
{
if(USART2_RX_STA&0x4000) //接收到了0x0d
{
if(Res!=0x0a)USART2_RX_STA=0; //接收错误,重新开始
else USART2_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART2_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
USART2_RX_STA++;
if(USART2_RX_STA>(USART_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
#endif
/****************
串口三初始化程序
****************/
#if USART3_switch //如果使能了接收
//串口3中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
void Usart_3_init(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能USART3,GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
//USART3_TX GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.10
//USART3_RX GPIOB.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PB11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.11
//Usart3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART3 初始化设置
USART_InitStructure.USART_BaudRate = DEBUG_USART3_BAUDRATE; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART3, &USART_InitStructure); //初始化串口3
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口3
USART_ClearFlag(USART3, USART_FLAG_TC);
}
void USART3_IRQHandler(void) //串口3中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART3); //读取接收到的数据
if((USART3_RX_STA&0x8000)==0) //接收未完成
{
if(USART3_RX_STA&0x4000) //接收到了0x0d
{
if(Res!=0x0a)USART3_RX_STA=0; //接收错误,重新开始
else USART3_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART3_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART3_RX_STA&0X3FFF]=Res ;
USART3_RX_STA++;
if(USART3_RX_STA>(USART_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
#endif
/****************
串口四初始化程序
****************/
#if UART4_switch //如果使能了接收
//串口4中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
void Uart_4_init(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能UART4,GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
USART_DeInit(UART4); //复位串口4
//UART4_TX GPIOC.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC.10
//UART4_RX GPIOC.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PC11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC.11
//Uart4 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = DEBUG_UART4_BAUDRATE; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(UART4, &USART_InitStructure); //初始化串口4
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(UART4, ENABLE); //使能串口4
USART_ClearFlag(UART4, USART_FLAG_TC);
}
void UART4_IRQHandler(void) //串口4中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(UART4); //读取接收到的数据
if((UART4_RX_STA&0x8000)==0)//接收未完成
{
if(UART4_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)UART4_RX_STA=0;//接收错误,重新开始
else UART4_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)UART4_RX_STA|=0x4000;
else
{
USART_RX_BUF[UART4_RX_STA&0X3FFF]=Res ;
UART4_RX_STA++;
if(UART4_RX_STA>(USART_REC_LEN-1))UART4_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
#endif
/****************
串口五初始化程序
****************/
#if UART5_switch //如果使能了接收
//串口5中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
void Uart_5_init(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能UART5,GPIOC D时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
USART_DeInit(UART5); //复位串口5
//UART5_TX GPIOC.12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC.12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC.12
//UART5_RX GPIOD5初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PD5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD.5
//Uart5 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//UART 初始化设置
USART_InitStructure.USART_BaudRate = DEBUG_UART5_BAUDRATE; //串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Rx | USART_Mode_Tx; //收发模式
USART_Init(UART5, &USART_InitStructure); //初始化串口5
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); //开启串口接受中断
USART_Cmd(UART5, ENABLE); //使能串口5
USART_ClearFlag(UART5, USART_FLAG_TC);
}
void UART5_IRQHandler(void) //串口5中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(UART5); //读取接收到的数据
if((UART5_RX_STA&0x8000)==0) //接收未完成
{
if(UART5_RX_STA&0x4000) //接收到了0x0d
{
if(Res!=0x0a)UART5_RX_STA=0;//接收错误,重新开始
else UART5_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)UART5_RX_STA|=0x4000;
else
{
USART_RX_BUF[UART5_RX_STA&0X3FFF]=Res ;
UART5_RX_STA++;
if(UART5_RX_STA>(USART_REC_LEN-1))UART5_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntExit();
#endif
}
#endif
PWM程序
#ifndef _pwm_h
#define _pwm_h
#include "sys.h"
/*****************************************************
PWM IO口对应
PWM 通道 IO口 PWM 通道 IO口
PWM1 1 PA8 PWM2 1 PA0
PWM1 2 PA9 PWM2 2 PA1
PWM1 3 PA10 PWM2 3 PA2
PWM1 4 PA11 PWM2 4 PA3
******************************************************
PWM 通道 IO口 PWM 通道 IO口
PWM3 1 PA6 PWM4 1 PB6
PWM3 2 PA7 PWM4 2 PB7
PWM3 3 PB0 PWM4 3 PB8
PWM3 4 PB1 PWM4 4 PB9
******************************************************
PWM 通道 IO口 PWM 通道 IO口
PWM5 1 PA0 PWM8 1 PC6
PWM5 2 PA1 PWM8 2 PC7
PWM5 3 PA2 PWM8 3 PC8
PWM5 4 PA3 PWM8 4 PC9
*****************************************************/
#define PWM_ON 1
#define PWM_OFF 0
#define PWM_CH_ON 1
#define PWM_CH_OFF 0
/*******************PWM开关*********************/
/***开启---PWM_ON***/ /***关闭--PWM_OFF***/
#define PWM1_switch PWM_OFF //默认关闭
#define PWM2_switch PWM_OFF //默认关闭
#define PWM3_switch PWM_OFF //默认关闭
#define PWM4_switch PWM_OFF //默认关闭
#define PWM5_switch PWM_OFF //默认关闭
/*******************PWM_CH开关*********************/
/***开启---PWM_CH_ON***/ /***关闭--PWM_CH_OFF***/
#define PWMCH1_switch PWM_CH_OFF //默认关闭
#define PWMCH2_switch PWM_CH_OFF //默认关闭
#define PWMCH3_switch PWM_CH_OFF //默认关闭
#define PWMCH4_switch PWM_CH_OFF //默认关闭
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
//注:尽量避免不同PWM使用相同通道,避免误开PWM//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
/*********************
设置PWM的自动重装载值
*********************/
#define PWM1_arr 199
#define PWM2_arr 199
#define PWM3_arr 199
#define PWM4_arr 199
#define PWM5_arr 199
#define PWM8_arr 199
/*********************
设置PWM的自动重装载值
*********************/
#define PWM1_psc 7199
#define PWM2_psc 7199
#define PWM3_psc 7199
#define PWM4_psc 7199
#define PWM5_psc 7199
#define PWM8_psc 7199
void PWM_Init(void);
#endif
#include "pwm.h"
void PWM_Init(void)
{
TIM_OCInitTypeDef TIM_OCInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
/***********************
PWM1设置(如果开启了PWM1)
***********************/
#if PWM1_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 开启复用时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 ; //通道1设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ; //通道2设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 ; //通道3设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 ; //通道4设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
//初始化TIM1基础设置
TIM_DeInit( TIM1 );
TIM_TimeBaseInitStruct.TIM_Period = PWM1_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM1_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM1, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM1, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM1, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM1, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM1, ENABLE );
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd( TIM1, ENABLE );
#endif
/***********************
PWM2设置(如果开启了PWM2)
***********************/
#if PWM2_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ; //通道1设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 ; //通道2设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 ; //通道3设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 ; //通道4设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
//初始化TIM1基础设置
TIM_DeInit( TIM2 );
TIM_TimeBaseInitStruct.TIM_Period = PWM2_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM2_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM2, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM2, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM2, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM2, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM2, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM2, ENABLE );
TIM_Cmd( TIM2, ENABLE );
#endif
/***********************
PWM3设置(如果开启了PWM3)
***********************/
#if PWM3_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 ; //通道1设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 ; //通道2设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ; //通道3设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 ; //通道4设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
//初始化TIM3基础设置
TIM_DeInit( TIM3 );
TIM_TimeBaseInitStruct.TIM_Period = PWM3_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM3_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM3, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM3, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM3, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM3, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM3, ENABLE );
TIM_Cmd( TIM3, ENABLE );
#endif
/***********************
PWM4设置(如果开启了PWM4)
***********************/
#if PWM4_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE );
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 ; //通道1设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 ; //通道2设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 ; //通道3设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ; //通道4设置
GPIO_Init( GPIOB, &GPIO_InitStruct );
#endif
//初始化TIM3基础设置
TIM_DeInit( TIM4 );
TIM_TimeBaseInitStruct.TIM_Period = PWM4_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM4_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM4, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM4, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM4, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM4, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM4, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM4, ENABLE );
TIM_Cmd( TIM4, ENABLE );
#endif
/***********************
PWM5设置(如果开启了PWM5)
***********************/
#if PWM5_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, ENABLE );
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ; //通道1设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1 ; //通道2设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 ; //通道3设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 ; //通道4设置
GPIO_Init( GPIOA, &GPIO_InitStruct );
#endif
//初始化TIM5基础设置
TIM_DeInit( TIM5 );
TIM_TimeBaseInitStruct.TIM_Period = PWM5_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM5_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM5, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM5, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM5,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM5, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM5,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM5, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM5,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM5, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM5,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM5, ENABLE );
TIM_Cmd( TIM5, ENABLE );
#endif
/***********************
PWM8设置(如果开启了PWM8)
***********************/
#if PWM8_switch
//时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM8, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 开启复用时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO配置
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
#if PWMCH1_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 ; //通道1设置
GPIO_Init( GPIOC, &GPIO_InitStruct );
#endif
#if PWMCH2_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 ; //通道2设置
GPIO_Init( GPIOC, &GPIO_InitStruct );
#endif
#if PWMCH3_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 ; //通道3设置
GPIO_Init( GPIOC, &GPIO_InitStruct );
#endif
#if PWMCH4_switch
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ; //通道4设置
GPIO_Init( GPIOC, &GPIO_InitStruct );
#endif
//初始化TIM1基础设置
TIM_DeInit( TIM8 );
TIM_TimeBaseInitStruct.TIM_Period = PWM8_arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = PWM8_psc;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit( TIM8, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式1
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性——高极性
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
TIM_OCInitStruct.TIM_Pulse = 199;//比较值CCR,可以不用配置,因为后期肯定要该
#if PWMCH1_switch
TIM_OC1Init( TIM8, &TIM_OCInitStruct );
TIM_OC1PreloadConfig(TIM8,TIM_OCPreload_Enable);
#endif
#if PWMCH2_switch
TIM_OC2Init( TIM8, &TIM_OCInitStruct );
TIM_OC2PreloadConfig(TIM8,TIM_OCPreload_Enable);
#endif
#if PWMCH3_switch
TIM_OC3Init( TIM8, &TIM_OCInitStruct );
TIM_OC3PreloadConfig(TIM8,TIM_OCPreload_Enable);
#endif
#if PWMCH4_switch
TIM_OC4Init( TIM8, &TIM_OCInitStruct );
TIM_OC4PreloadConfig(TIM8,TIM_OCPreload_Enable);
#endif
TIM_ARRPreloadConfig( TIM8, ENABLE );
TIM_CtrlPWMOutputs(TIM8, ENABLE);
TIM_Cmd( TIM8, ENABLE );
#endif
}
|