版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wekic/article/details/84751677
这个是初始化的头文件
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "stm32f10x.h"
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
#define debug 2
#if (debug==1) //库打印
#define COM_Printf printf
#elif (debug==2)//自建打印
void COM_Printf(u8 type ,char *fmt, ...);
#else //无打印
void COM_Printf(u8 type char *fmt, ...);
#endif
#if 1
typedef enum
{
COM1 = 0,
COM2 = 1,
COM3 = 2,
COM4 = 3,
COM5 = 4,
} COM_TypeDef;
void Uart1_init(u32 bound);
int fputc(int ch, FILE *f);
void Usart_Init(COM_TypeDef COMx, u32 Baud, u8 Priority1, u8 Priority2);
void Usart_SendByte(COM_TypeDef COMx, u8 Dat);
void Usart_SendString(COM_TypeDef COMx, u8 * Dat,u16 len);
//==================宏开关============================================
//COM开关
#define COM1_OFFON 0
#if (COM1_OFFON == 1)
extern RingBuffType COM1Dat;
extern COMnDealType COM1Deal;
#endif
#define COM2_OFFON 0
#if (COM2_OFFON == 1)
extern RingBuffType COM2Dat;
#endif
#define COM3_OFFON 0
#if (COM3_OFFON == 1)
extern RingBuffType COM3Dat;
#endif
#define COM4_OFFON 0
#if (COM4_OFFON == 1)
extern RingBuffType COM4Dat;
#endif
#define COM5_OFFON 0
#if (COM5_OFFON == 1)
extern RingBuffType COM5Dat;
#endif
//=======COM1=======
//默认: PA9 :Tx PA10:Rx (PA:APB2 Usart1:APB2)
//映射: PB6 :Tx PB7 :Rx (PA:APB2 Usart1:APB2)
#define Mapping_COM1OFFON 0
#define EVAL_COM1 USART1
#define EVAL_COM1_CLK RCC_APB2Periph_USART1
#define EVAL_COM1_IRQn USART1_IRQn
#if (Mapping_COM1OFFON == 0) //默认
#define EVAL_COM1_TX_PIN GPIO_Pin_9
#define EVAL_COM1_TX_GPIO_PORT GPIOA
#define EVAL_COM1_TX_GPIO_CLK RCC_APB2Periph_GPIOA
#define EVAL_COM1_RX_PIN GPIO_Pin_10
#define EVAL_COM1_RX_GPIO_PORT GPIOA
#define EVAL_COM1_RX_GPIO_CLK RCC_APB2Periph_GPIOA
#elif (Mapping_COM1OFFON == 1)
#define EVAL_COM1_TX_PIN GPIO_Pin_6
#define EVAL_COM1_TX_GPIO_PORT GPIOB
#define EVAL_COM1_TX_GPIO_CLK RCC_APB2Periph_GPIOB
#define EVAL_COM1_RX_PIN GPIO_Pin_7
#define EVAL_COM1_RX_GPIO_PORT GPIOB
#define EVAL_COM1_RX_GPIO_CLK RCC_APB2Periph_GPIOB
#endif
//=======COM2=======
//默认: PA2 :Tx PA3 :Rx (PA:APB2 Usart2:APB1)
//映射: PD5 :Tx PD6 :Rx (PA:APB2 Usart2:APB1)
#define Mapping_COM2OFFON 0
#define EVAL_COM2 USART2
#define EVAL_COM2_CLK RCC_APB1Periph_USART2
#define EVAL_COM2_IRQn USART2_IRQn
#if (Mapping_COM2OFFON == 0) //默认
#define EVAL_COM2_TX_PIN GPIO_Pin_2
#define EVAL_COM2_TX_GPIO_PORT GPIOA
#define EVAL_COM2_TX_GPIO_CLK RCC_APB2Periph_GPIOA
#define EVAL_COM2_RX_PIN GPIO_Pin_3
#define EVAL_COM2_RX_GPIO_PORT GPIOA
#define EVAL_COM2_RX_GPIO_CLK RCC_APB2Periph_GPIOA
#elif (Mapping_COM2OFFON == 1)
#define EVAL_COM2_TX_PIN GPIO_Pin_5
#define EVAL_COM2_TX_GPIO_PORT GPIOD
#define EVAL_COM2_TX_GPIO_CLK RCC_APB2Periph_GPIOD
#define EVAL_COM2_RX_PIN GPIO_Pin_6
#define EVAL_COM2_RX_GPIO_PORT GPIOD
#define EVAL_COM2_RX_GPIO_CLK RCC_APB2Periph_GPIOD
#endif
//=======COM3=======
//默认: PB10:Tx PB11 :Rx (PA:APB2 Usart3:APB1) 0
//映射: PC10:Tx PC11 :Rx (PA:APB2 Usart3:APB1) 1 //部分映射
//映射: PD8 :Tx PD9 :Rx (PA:APB2 Usart3:APB1) 2 //全部映射
#define Mapping_COM3OFFON 0
/* 默认 部分映射 全部映射
USART3_RX | PB11 | PC11 | PD9
USART3_TX | PB12 | PC12 | PD10
USART3_CTS | PB13 | PD11
USART3_RTS | PB14 | PD12
*/
#define EVAL_COM3 USART3
#define EVAL_COM3_CLK RCC_APB1Periph_USART3
#define EVAL_COM3_IRQn USART3_IRQn
#if (Mapping_COM3OFFON==0) //默认
#define EVAL_COM3_TX_PIN GPIO_Pin_10
#define EVAL_COM3_TX_GPIO_PORT GPIOB
#define EVAL_COM3_TX_GPIO_CLK RCC_APB2Periph_GPIOB
#define EVAL_COM3_RX_PIN GPIO_Pin_11
#define EVAL_COM3_RX_GPIO_PORT GPIOB
#define EVAL_COM3_RX_GPIO_CLK RCC_APB2Periph_GPIOB
#elif (Mapping_COM3OFFON==1) //部分映射
#define EVAL_COM3_TX_PIN GPIO_Pin_10
#define EVAL_COM3_TX_GPIO_PORT GPIOC
#define EVAL_COM3_TX_GPIO_CLK RCC_APB2Periph_GPIOC
#define EVAL_COM3_RX_PIN GPIO_Pin_11
#define EVAL_COM3_RX_GPIO_PORT GPIOC
#define EVAL_COM3_RX_GPIO_CLK RCC_APB2Periph_GPIOC
#elif (Mapping_COM3OFFON==2)// 全部映射
#define EVAL_COM3_TX_PIN GPIO_Pin_8
#define EVAL_COM3_TX_GPIO_PORT GPIOD
#define EVAL_COM3_TX_GPIO_CLK RCC_APB2Periph_GPIOD
#define EVAL_COM3_RX_PIN GPIO_Pin_9
#define EVAL_COM3_RX_GPIO_PORT GPIOD
#define EVAL_COM3_RX_GPIO_CLK RCC_APB2Periph_GPIOD
#endif
//=======COM4=======
//默认: PC10:Tx PC11 :Rx (PA:APB2 Uart4:APB1)
#define EVAL_COM4 UART4
#define EVAL_COM4_CLK RCC_APB1Periph_UART4
#define EVAL_COM4_TX_PIN GPIO_Pin_10
#define EVAL_COM4_TX_GPIO_PORT GPIOC
#define EVAL_COM4_TX_GPIO_CLK RCC_APB2Periph_GPIOC
#define EVAL_COM4_RX_PIN GPIO_Pin_11
#define EVAL_COM4_RX_GPIO_PORT GPIOC
#define EVAL_COM4_RX_GPIO_CLK RCC_APB2Periph_GPIOC
#define EVAL_COM4_IRQn UART4_IRQn
//=======COM5=======
//默认: PC12:Tx PD2 :Rx (PA:APB2 Uart5:APB1)
#define EVAL_COM5 UART5 //串口号
#define EVAL_COM5_CLK RCC_APB1Periph_UART5 //串口时钟
#define EVAL_COM5_TX_PIN GPIO_Pin_12 //发送管脚
#define EVAL_COM5_TX_GPIO_PORT GPIOC //发送管脚端
#define EVAL_COM5_TX_GPIO_CLK RCC_APB2Periph_GPIOC //发送管脚时钟
#define EVAL_COM5_RX_PIN GPIO_Pin_2 //接收管脚
#define EVAL_COM5_RX_GPIO_PORT GPIOD //接收管脚端
#define EVAL_COM5_RX_GPIO_CLK RCC_APB2Periph_GPIOD //接收管脚时钟
#define EVAL_COM5_IRQn UART5_IRQn //串口中断号
#endif
#endif
这个是初始化的.c文件
#include "sys.h"
#include "usart.h"
#include "stdio.h"
//////////////////////////////////////////////////////////////////////////////////
#if 1
#define COMn
//===================串口中断列表=========================
//选择串口号
USART_TypeDef *COMn_USART[COMn] = {EVAL_COM1, EVAL_COM2, EVAL_COM3
#if STM32F10X_HD
, EVAL_COM4, EVAL_COM5
#endif
};
//串口中断号
const uint16_t COMn_IRQn[COMn] = {EVAL_COM1_IRQn, EVAL_COM2_IRQn, EVAL_COM3_IRQn
#if STM32F10X_HD
, EVAL_COM4_IRQn, EVAL_COM5_IRQn
#endif
};
//串口外设时钟
const uint32_t COMn_USART_CLK[COMn] = {EVAL_COM1_CLK, EVAL_COM2_CLK, EVAL_COM3_CLK
#if STM32F10X_HD
, EVAL_COM4_CLK, EVAL_COM5_CLK
#endif
};
//发送管脚时钟
const uint32_t COMn_TX_PORT_CLK[COMn] = {EVAL_COM1_TX_GPIO_CLK, EVAL_COM2_TX_GPIO_CLK, EVAL_COM3_TX_GPIO_CLK
#if STM32F10X_HD
, EVAL_COM4_TX_GPIO_CLK, EVAL_COM5_TX_GPIO_CLK
#endif
};
//===================串口管脚列表==========================
//发送管脚端口
GPIO_TypeDef *COMn_TX_PORT[COMn] = {EVAL_COM1_TX_GPIO_PORT, EVAL_COM2_TX_GPIO_PORT, EVAL_COM3_TX_GPIO_PORT
#if STM32F10X_HD
, EVAL_COM4_TX_GPIO_PORT, EVAL_COM5_TX_GPIO_PORT
#endif
};
//接受管脚端口
GPIO_TypeDef *COMn_RX_PORT[COMn] = {EVAL_COM1_RX_GPIO_PORT, EVAL_COM2_RX_GPIO_PORT, EVAL_COM3_RX_GPIO_PORT
#if STM32F10X_HD
, EVAL_COM4_RX_GPIO_PORT, EVAL_COM5_RX_GPIO_PORT
#endif
};
//接受管脚时钟
const uint32_t COMn_RX_PORT_CLK[COMn] = {EVAL_COM1_RX_GPIO_CLK, EVAL_COM2_RX_GPIO_CLK, EVAL_COM3_RX_GPIO_CLK
#if STM32F10X_HD
, EVAL_COM4_RX_GPIO_CLK, EVAL_COM5_RX_GPIO_CLK
#endif
};
//发送管脚
const uint16_t COMn_TX_PIN[COMn] = {EVAL_COM1_TX_PIN, EVAL_COM2_TX_PIN, EVAL_COM3_TX_PIN
#if STM32F10X_HD
, EVAL_COM4_TX_PIN, EVAL_COM5_TX_PIN
#endif
};
//接受管脚
const uint16_t COMn_RX_PIN[COMn] = {EVAL_COM1_RX_PIN, EVAL_COM2_RX_PIN, EVAL_COM3_RX_PIN
#if STM32F10X_HD
, EVAL_COM4_RX_PIN, EVAL_COM4_RX_PIN
#endif
};
//==================函数===================================================
//初始化函数 参数(串口号,波特率,抢占优先级,子优先级)
void Usart_Init(COM_TypeDef COMx, u32 Baud, u8 Priority1, u8 Priority2)
{
//=======COM1=======
//默认: PA9 :Tx PA10:Rx (PA:APB2 Usart1:APB2)
//映射: PB6 :Tx PB7 :Rx (PA:APB2 Usart1:APB2)
//=======COM2=======
//默认: PA2 :Tx PA3 :Rx (PA:APB2 Usart2:APB1)
//映射: PD5 :Tx PD6 :Rx (PA:APB2 Usart2:APB1)
//=======COM3=======
//默认: PB10:Tx PB11 :Rx (PA:APB2 Usart3:APB1)
//映射: PD8 :Tx PD9 :Rx (PA:APB2 Usart3:APB1)
//映射: PC10:Tx PC11 :Rx (PA:APB2 Usart3:APB1)
//=======COM4=======
//默认: PC10:Tx PC11 :Rx (PA:APB2 Usart4:APB1)
//=======COM5=======
//默认: PC12:Tx PD2 :Rx (PA:APB2 Usart5:APB1)
GPIO_InitTypeDef GPIO_InitStructure; //管脚配置
USART_InitTypeDef USART_InitStructure; //串口配置
NVIC_InitTypeDef NVIC_InitStructure; //中断优先级配置
//=====================外设时钟配置==========================================================================
/* 使能管脚时钟 */
// RCC_APB2PeriphClockCmd(COMn_TX_PORT_CLK[COMx] | COMn_RX_PORT_CLK[COMx] | RCC_APB2Periph_AFIO, ENABLE);
/* 使能串口外设时钟 */
if(COMx == COM1) {
#if (Mapping_COM1OFFON == 1) //串口1开管脚重映射
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
#endif
RCC_APB2PeriphClockCmd(COMn_USART_CLK[COMx], ENABLE);
} else {
/* 串口管脚软件重映射 */
if(COMx == COM2) {
#if (Mapping_COM2OFFON == 1) //串口2开管脚重映射
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
#endif
} else if(COMx == COM3) {
#if (Mapping_COM3OFFON == 1) //串口3开管脚重映射
GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
#elif (Mapping_COM3OFFON == 2)
GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);
#endif
}
RCC_APB1PeriphClockCmd(COMn_USART_CLK[COMx], ENABLE);
}
//==========串口管脚配置========================================================
/* 配置串口发送脚--->复用推挽输出 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = COMn_TX_PIN[COMx];
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(COMn_TX_PORT[COMx], &GPIO_InitStructure);
/* 配置串口接受脚--->浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = COMn_RX_PIN[COMx];
GPIO_Init(COMn_RX_PORT[COMx], &GPIO_InitStructure);
//==========串口参数配置======================
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_Rx | USART_Mode_Tx;
/* 根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器 */
USART_Init(COMn_USART[COMx], &USART_InitStructure);
/* 使能串口 */
USART_Cmd(COMn_USART[COMx], ENABLE);
/* 开启串口接受中断*/
USART_ITConfig(COMn_USART[COMx], USART_IT_RXNE, ENABLE);//开启串口接受中断
/* 清除串口发送完成标志(防止第一字节丢失)*/
USART_ClearFlag(COMn_USART[COMx], USART_FLAG_TC); //清除发送完成标志
//=======串口中断优先级配置==============================================================
//Usart1 NVIC 配置
if(Priority1 >= 15) {
Priority1 = 15;
}
if(Priority2 >= 15) {
Priority2 = 15;
}
NVIC_InitStructure.NVIC_IRQChannel = COMn_IRQn[COMx];
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = Priority1 ; //抢占优先级3 (0----15)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = Priority2; //子优先级3 (0----15)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
// if(COMn_USART[COMx] == USART1)
// COM_Printf(0,"波特率值 : %6.0ld \r\n",72000000/COMn_USART[COMx]->BRR );
// else
// COM_Printf(0,"波特率值 : %6.0ld \r\n",36000000/COMn_USART[COMx]->BRR );
}
//==============数据发送 ===========================================
/*
**********************************************************************
*功能:选择串口号发送单字节
*入口(COMx,DAT)
**********************************************************************
*/
void Usart_SendByte(COM_TypeDef COMx, u8 Dat)
{
COMn_USART[COMx]->DR = (u8) Dat;
while((COMn_USART[COMx]->SR & 0X40) == 0); //循环发送,直到发送完毕
// USART_SendData(COMn_USART[COMx], (u8)Dat);
// while(USART_GetFlagStatus(COMn_USART[COMx], USART_FLAG_TXE) == RESET);
}
void Usart_SendString(COM_TypeDef COMx, u8 *Dat, u16 len)
{
while(len--) {
Usart_SendByte( COMx, *Dat++);
}
}
//////////////////////////////////////////////////////////////////
#if (debug==1) //内部库输出
#ifndef __MICROLIB //加入以下代码,支持printf函数,而不需要选择use MicroLIB
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE {
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
// while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
// USART1->DR = (u8) ch;
Usart_SendByte( COM1, (uint8_t) ch );
return ch;
}
#else
int fputc(int ch, FILE *f)
{
// USART_SendData(USART1, (uint8_t) ch);
// while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
Usart_SendByte( COM1, (uint8_t) ch );
return ch;
}
int GetKey (void)
{
while (!(USART1->SR & USART_FLAG_RXNE));
return ((int)(USART1->DR & 0x1FF));
}
#endif
#elif (debug==2)
#include "string.h"
#include "stdarg.h"
#include "stdio.h"
//======LCD输出转接打印==========================================
//选择输出打印信息
const u8 enumA[] = {
0,
// 1, //AS608模块基础
// 2, //AS608应用
// 3, //ADC数据读取
// 4, //LED的状态
// 5, //温湿度模块
// 6, //温湿度模块
// 7, //FM24L64铁电模块
// 8, //打印风机信息
};
void COM_Printf(u8 type, char *fmt, ...)
{
u8 i;
u8 StrlenC = 0; //长度
u8 COM_StrDat[100] = {0}; //缓存
va_list ap; //定义个链表
for(i = 0; i < sizeof(enumA); i++) {
if(type == enumA[i] && type != 0) {
goto enumA1;
}
}
return ;
enumA1:
va_start(ap, fmt); //链表开始
vsprintf((char *)COM_StrDat, fmt, ap); //数据格式化
va_end(ap); //链表结束
StrlenC = strlen((char *)COM_StrDat);
Usart_SendString(COM1, COM_StrDat, StrlenC);
}
#else
void COM_Printf(u8 type, char *fmt, ...)
{
}
#endif
#endif