/*************************USART串口*****************************************/
#define PRINTF_COM USART1 //printf打印串口選擇 可選:USART1、USART2、USART3、UART4、UART5
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
OS_ENTER_CRITICAL();
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
OS_EXIT_CRITICAL();
return ch;
}
void USART_SendByte(USART_TypeDef *USART_COM,u8 c) //串口發送一個字節
{
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
USART_COM->DR = (u8)(c);
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
}
void USART_SendString(USART_TypeDef *USART_COM,unsigned char *s) //串口發送字符串函數
{
while(*s)
{
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
USART_COM->DR = (u8)(*s);
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
s++;
}
}
void USART_SendBuf(USART_TypeDef *USART_COM,unsigned char *buf,u16 len) //串口發送數組函數
{
while(len--)
{
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
USART_COM->DR = (u8)(*buf++);
while((USART_COM->SR&0X40)==0);//循環發送,直到發送完畢
}
}
void USART1_Config(u32 BaudRate) //串口1初始化函數
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//使能USART1,GPIOA時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
//GPIO端口設置
//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
//USART 初始化設置
USART_InitStructure.USART_BaudRate = 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
//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寄存器
USART_ClearFlag(USART1,USART_FLAG_TC);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //開啟串口接受中斷
USART_Cmd(USART1, ENABLE); //使能串口1
}
void USART2_Config(u32 BaudRate) //串口2初始化函數
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//時鐘使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA,D時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2時鐘
//GPIO端口設置
//TX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure);
//RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE); //復位串口2
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE); //停止復位
USART_InitStructure.USART_BaudRate = 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); //初始化串口
USART_ClearFlag(USART2,USART_FLAG_TC);
//中斷
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占優先級2級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級2級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開啟中斷
USART_Cmd(USART2, ENABLE); //使能串口
}
void USART3_Config(u32 BaudRate) //串口3初始化函數
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitValue;
USART_InitTypeDef USART_InitValue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
//GPIO端口設置
GPIO_InitValue.GPIO_Pin=GPIO_Pin_10;
GPIO_InitValue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitValue.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitValue);
GPIO_InitValue.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitValue.GPIO_Pin =GPIO_Pin_11;
GPIO_Init(GPIOB,&GPIO_InitValue);
USART_InitValue.USART_BaudRate = BaudRate;
USART_InitValue.USART_WordLength = USART_WordLength_8b;
USART_InitValue.USART_StopBits = USART_StopBits_1;
USART_InitValue.USART_Parity = USART_Parity_No;
USART_InitValue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitValue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3,&USART_InitValue);
USART_ClearFlag(USART3,USART_FLAG_TC);
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//配置串口接收非空中斷
NVIC_InitStructure.NVIC_IRQChannel =USART3_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =3; //搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能USART3中斷
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART3,ENABLE);
}
void UART4_Config(u32 BaudRate) //串口4初始化函數
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//注意UART4是掛載在APB1總線上的,用RCC_APB1PeriphClockCmd()函數初始化!
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
//GPIO端口設置
//UART4_TX PC.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //將UART4 的TX 配置為復用推挽輸出 AF_PP
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //輸出速度50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //推挽輸出模式 Out_PP
GPIO_Init(GPIOC, &GPIO_InitStructure);
//將UART4 的RX 配置為復用浮空輸入 IN_FLOATING
//UART4_RX PC.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空輸入 IN_FLOATING
GPIO_Init(GPIOC, &GPIO_InitStructure);
//UART4配置 N 8 1
USART_InitStructure.USART_BaudRate = BaudRate; //波特率
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_Rx | USART_Mode_Tx; //打開Rx接收和Tx發送功能
USART_Init(UART4 , &USART_InitStructure);
//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_ClearFlag(UART4,USART_FLAG_TC);
USART_ITConfig(UART4,USART_IT_RXNE,ENABLE);//配置串口接收非空中斷
USART_Cmd(UART4,ENABLE);
}
void UART5_Config(u32 BaudRate) //串口5初始化函數
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
//GPIO端口設置
//UART5_TX PC.12
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //輸出速度50MHz
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //推挽輸出模式 Out_PP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //將UART4 的TX 配置為復用推挽輸出 AF_PP
GPIO_Init(GPIOC, &GPIO_InitStructure);
//將UART5 的RX 配置為復用浮空輸入 IN_FLOATING
//UART5_RX PD.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空輸入 IN_FLOATING
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = BaudRate; //波特率
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_Rx | USART_Mode_Tx; //打開Rx接收和Tx發送功能
USART_Init(UART5 , &USART_InitStructure);
/* Enable the UART5 Interrupt */
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寄存器
USART_ClearFlag(UART5,USART_FLAG_TC);
USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//配置串口接收非空中斷
USART_Cmd(UART5,ENABLE);
}
/*******************************串口END***************************************/
//串口1中斷函數
void USART1_IRQHandler(void) //串口1中斷服務程序
{
u8 res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾)
{
res =USART_ReceiveData(USART1); //讀取接收到的數據
USART_SendData(USART1,res);
}
}
//串口2中斷函數
void USART2_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到數據
{
res =USART_ReceiveData(USART2); //讀取接收到的數據
USART_SendData(USART2,res);
}
}
//串口3中斷函數
void USART3_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收到數據
{
res =USART_ReceiveData(USART3); //讀取接收到的數據
USART_SendData(USART3,res);
}
}
//串口4中斷函數
void UART4_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET) //接收到數據
{
res =USART_ReceiveData(UART4); //讀取接收到的數據
USART_SendData(UART4,res);
}
}
//串口5中斷函數
void UART5_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET) //接收到數據
{
res =USART_ReceiveData(UART5); //讀取接收到的數據
USART_SendData(UART5,res);
}
}
//注:中斷函數名是固定的,不能更改(可在啟動文件里更改,不建議更改),
//串口使用方法:想要哪個串口就初使化哪個串口,然后用發送函數就可以發送數據,當然,這里提供了printf重定向了,你也可以直接用printf函數發送。
//使用示例:
int main(void)
{
USART1_Config(9600); //初使化串口1,波特率為9600
while(1)
{
printf("你好! \r\n"); //\r\n是回車符
}
}
//接收串口數據在串口1中斷函數里接收,和51一樣。
//串口1 引腳: PA9: TXD PA10:RXD
//串口2 引腳: PA2: TXD PA3: RXD
//串口3 引腳: PB10:TXD PB11:RXD
//串口4 引腳: PC10:TXD PC11:RXD
//串口5 引腳: PC12:TXD PD2: RXD
//ps:stm32只有串口1支持串口下載燒寫程序,所以我們一般都用串口1和電腦互動 |