在STM32里,串口通信是USART,STM32可以通过串口和其他设备进行传输并行数据,是全双工,异步时钟控制,设备之间是点对点的传输。对应的STM32引脚分别是RX和TX端。STM32的串口资源有USART1、USART2、USART3.
串口的几个重要的参数:
- 波特率,串口通信的速率
- 空闲,一般为高电平
- 起始位,标志一个数据帧的开始,固定为低电平。当数据开始发送时,产生一个下降沿。(空闲–>起始位)
- 数据位,发送数据帧,1为高电平,0为低电平。低位先行。
比如 发送数据帧0x0F 在数据帧里就是低位线性 即 1111 0000
- 校验位,用于数据验证,根据数据位的计算得来。有奇校验,偶校验和无校验。
- 停止位,用于数据的间隔,固定为高电平。数据帧发送完成后,产生一个上升沿。(数据传输–>停止位)
注意:
1.在数据传输期间不能复位TE位,否则将破坏TX脚上的数据,因为波特率计数器停止计数。 正在传输的当前数据将丢失。
2. TE位被激活后将发送一个空闲帧。
库函数配置
串口配置一般步骤:
- 串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();
- 串口复位:USART_DeInit(); 这一步不是必须的
- GPIO端口模式设置:GPIO_Init(); 模式可设置为推挽复用以及浮空输入或者上拉输入
- 串口参数初始化:USART_Init();
- 开启中断并且初始化NVIC(若有中断就配置这个) NVIC_Init();USART_ITConfig();
- 使能串口:USART_Cmd();
- 编写中断处理函数:USARTx_IRQHandler();
- 串口数据收发:void USART_SendData();//发送数据到串口//USART_ReceiveData();
串口传输状态获取:
- FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
- void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
void RCC_Configuration(void)
{
//----------使用外部RC晶振-----------
RCC_DeInit(); //初始化为缺省值
RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ
RCC_PLLCmd(ENABLE); //Enable PLLCLK
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock
while(RCC_GetSYSCLKSource()!=0x08); //等至PLL被用作系统时钟源
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB使用系统时钟,HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //APB2为HCLK/1,PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2
/*******配置RCC时钟,打开相应外设时钟******/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能APB2外设的GPIOA的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能APB1外设的USART2的时钟//用到哪些开哪些
}
USART初始化配置
void USART1_Configuration(u32 bound)
{
//定义串口1的初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
//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 = bound;//串口波特率
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
}
使用GPIO_InitTypeDef和USART_InitTypeDef构体定义一个GPIO初始化变量以及一个USART初始化变量,这两个结构体这里不再赘述。
USART中断服务函数
if( (USART_GetITStatus(USART2, USART_IT_TXE) != RESET) )
{
//程序
USART_ITConfig(USART2,USART_IT_TXE,DISABLE);
}
if( (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) )
{
temp = USART_ReceiveData(USART2);
USART_SendData(USART2, temp);
}
void USART2_IRQHandler(void)
{
if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET)
{
Buffer_Rx[RxCNT++] = USART_ReceiveData(USART2);
}
}
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
{
Buffer_Rx[RX_Num++] = USART_ReceiveData(USART2);
USART_SendData(USART2,Buffer_Tx[TX_Num]);
if(RX_Num == buffer_size) RX_Num = 0,TX_Num = 0;
}
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/*调用时记得选择分组,要么在main里加,要么在这里加,配置一次即可*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
/**************用哪个加哪个,加在后面就行***********************/
/*这里用的是USART1的中断*/
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //对应的中断向量通道//在stm32f10x.h中可以找到对应的外部通道名字
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
}
主函数
int main(void)
{
uint8_t a[10] = {65,66,67,68,69,70,71,72,73,74};
GPIO_LED_Config();
USART1_Config();
USART_SendByte(DEBUG_USARTx,0x63);
USART_SendTwoByte(DEBUG_USARTx,0x4344);
USART_SendArray(DEBUG_USARTx,a,10);
USART_SendString(DEBUG_USARTx, "\n欢迎来到学习STM32的世界\n");
printf("串口测试输出\n");
while(1)
{
//此处敲对应代码
}
}