STM32—串口发送于接收
目录
串口通讯
串口通讯 (Serial Communication) 是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此 大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试 信息。
所以很有必要去了解串口。
配置
既然想要使用串口,那么就需要懂得配置,只有配置出我们想要的,才能保证设备之间的通讯。
首先,寻找到与串口相对于的IO口,这里我以PA9,PA10,为例。
1、初始化GPIO口
USART_GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStruct ;
//使能时钟一定要提前,不然会出现乱码的情况
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP ; //复用输出,根据手册得出
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct );
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING ;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct );
USART_InitTypeDef USART_InitStruct;
}
串口的发送端口配置模式:复用输出,配置其他的模式会出现乱码。
串口的接收端口配置模式:浮空输入,因为是接收端口。
2、初始化串口
USART_Config()
{
USART_InitTypeDef USART_InitStruct;
//下面的配置都是依据通讯设备之间的约定来配置的,二者必须约定一致,否则会出现乱码
USART_InitStruct.USART_BaudRate=115200;//
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_Init( USART1,&USART_InitStruct);
NVIC_Config();//中断初始化
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//当符合条件就进入中断
USART_Cmd(USART1,ENABLE);//最后一步,使能串口
}
这样只是把串口配置好了,但是二者的协议还没写好,对于STM32来说,只要调用相应的函数就可以。
想要对方能接收数据,那么二者检验位、停止位、波特路等等都是必须一致的,这样传输的数据才能是准确无误的。
1——发送一个字节
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
对于STM32来说,好多底层的代码都是已经写好了,我们只需要调用即可,比如上面的发送一个字节,等待发送字节完成。
2——发送数组
void USART_SendArray(USART_TypeDef* USARTx,uint8_t *array,uint16_t num)
{
uint8_t i;
for(i=0;i<num;i++)
{
USART_SendByte(USARTx,array[i]);
}
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)== RESET);
}
对于多个数据来说,等待的时间就不是说字节等待了,而是直接等待数据发送完成。
3——发送字符串
void USART_SendString(USART_TypeDef* USARTx,char *str)
{
unsigned int i=0;
while(*(str+i)!='\0')
{
USART_SendByte(USARTx,*(str+i));
i++;
}
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)== RESET);
}
因为字符串的结尾标志就是 '\0',所以我们直接循环发送到结尾标识符即可。
4——发送半字
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
uint8_t temp_h, temp_l;
/* 取出高八位 */
temp_h = (ch&0XFF00)>>8;
/* 取出低八位 */
temp_l = ch&0XFF;
/* 发送高八位 */
USART_SendData(pUSARTx,temp_h);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
/* 发送低八位 */
USART_SendData(pUSARTx,temp_l);
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
5——串口的重定向
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}
重定向是为了更加完美的使用printf()等函数;
注:
为了更加明了的实验,我们在接收信息后产生中断,从而进行发送信息到串口,这样就能显示出我们的数据是否已经被接受;
中断配置
static void NVIC_Config()
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中断控制器组选择 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
/* 抢断优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
STM32f10x_it.c
void USART1_IRQHandler()
{
uint8_t ucTemp;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData(USART1);
USART_SendData(USART1,ucTemp);
}
}