stm32---串口(USART)通讯

stm32—串口(USART)通讯

一、通讯概述:

一个通讯协议大体从4点了解:
1、数据传送方式(串行、并行)
串行: 数据按位顺序传输,速度慢,占用资源少。如: FSMC
并行: 数据各个位同时传输,速度快,占用资源多;如:USART、SPI、ICC

2、数据通讯方式(单工、半双工、全双工)
单工 : 在任意时刻只能进行一个方向的通讯,即是一个固定的发送设备,另一个固定的接收设备。
半双工: 两个设备之间可以收发数据,但不能在同一时刻。
全双工: 在同一时刻,两台设备之间可以收发数据。
3、数据同步方向(异步、同步)
异步特点 :
由于异步通讯是没有时钟SCLK约束的;使得双方接收和发送数据不同步(接收方根本不知道你什么时候发了数据过来,更不知数据是从哪一位有效);所以你发送一个字符数据时,必须先发送一个起始位(告诉对方开始发数据了),然后才有数据字符和奇偶校验(可选),最后发送结束后告诉对方(发送停止位)

由此可见;异步USART通讯不带时钟约束,双方必须设定好波特率、数据格式来达到双方数据收发稳定:
1、波特率
2、数据格式(起始位、有效数据位、奇偶校验位、停止位)

同步 特点:
1、数据传输是以数据块传输(多个字符组成数据流);
2、在一个数据块内数据是没间隔的;
3、因为一次传输的数据块包含数据比较多,所以接收时钟和发送时钟严格同步,通常要有同步时钟SCLK;
4、通讯上方时钟是连在一起的,提供同步时钟。
5、通讯双方接收与发送是同步的(时刻相同)

4、数据通讯速度(比特率、波特率)

二、基于固件库如何配置串口通讯

1、配置时钟:GPUO口的时钟、串口时钟、引脚复用时钟
2、配置GPIO结构体
3、配置串口结构体
4、串口发送

以USART1(PA9位TX,PA10位RX)为例
1、配置时钟:GPIO口的时钟、串口时钟、引脚复用时钟

void Usart_Init(void)
{ 
//使能GPIO口的时钟、串口时钟、引脚复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
}

2、配置GPIO结构体

void Usart_Init(void)
{ //定义GPIOA的结构体   
GPIO_InitTypeDef gpio_initStruct; 
//配置GPIOA9 TX 复用功能推挽输出模式GPIO_Mode_AF_PP
	  gpio_initStruct.GPIO_Mode   = GPIO_Mode_AF_PP;
	  gpio_initStruct.GPIO_Pin    = GPIO_Pin_9;
	  gpio_initStruct.GPIO_Speed  = GPIO_Speed_10MHz;
	  GPIO_Init(GPIOA, &gpio_initStruct);
//配置GPIOA10  RX  浮空输入模式GPIO_Mode_IN_FLOATING
	  gpio_initStruct.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
	  gpio_initStruct.GPIO_Pin    = GPIO_Pin_10;
     GPIO_Init(GPIOA, &gpio_initStruct);
}	

3、配置串口结构体

异步串口结构:

typedef struct
{
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */

  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */

  uint16_t USART_StopBits;             /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */

  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */
 
  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */

  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;

1、USART_BaudRate : 波特率(配置波特率)
2、USART_WordLength : 字节 (配置控制数据位的字节:八、九位)
3、USART_StopBits : 停止位(配置停止位:0.5、1、5、2)
4、USART_Parity : 校验位(配置校验位、无、奇、偶)
5、USART_Mode : 模式(配置工作模式收/发)
6、USART_HardwareFlowControl : 硬件流控制

同步时钟的USART串口结构:

typedef struct
{

  uint16_t USART_Clock;   /*!< Specifies whether the USART clock is enabled or disabled.
                               This parameter can be a value of @ref USART_Clock */

  uint16_t USART_CPOL;    /*!< Specifies the steady state value of the serial clock.
                               This parameter can be a value of @ref USART_Clock_Polarity */

  uint16_t USART_CPHA;    /*!< Specifies the clock transition on which the bit capture is made.
                               This parameter can be a value of @ref USART_Clock_Phase */

  uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted
                               data bit (MSB) has to be output on the SCLK pin in synchronous mode.
                               This parameter can be a value of @ref USART_Last_Bit */
} USART_ClockInitTypeDef;

1、USART_Clock : 同步时钟 (配置是否打开)
2、USART_CPOL : 极性(配至串口空闲位高电平、低电平)
3、USART_CPHA : 相位(配置选择边沿)
4、USART_LastBit : 最后一个时钟(配置使能还是关闭)

配置串口结构体如下:

void Usart_Init(void)
{//定义串口结构体    
 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);
//使能串口
USART_Cmd(USART1, ENABLE);
}

4、串口函数

//初始化串口
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
//串口使能函数
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
//中断配置函数
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
//串口发送函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
//串口接收函数
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
//获取相应的串口标志位
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
//中断状态获取
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
USART_FLAG描述
USART_FLAG_CTSCTS标志位
USART_FLAG_LBDLIN中断标志位
USART_FLAG_TXE发送数据寄存器空标志位
USART_FLAG_TC发送完成标志位
USART_FLAG_RXNE接收数据寄存器非空标志位
USART_FLAG_IDLE空闲总线标志位
USART_FLAG_ORE溢出错误标志位
USART_FLAG_NE噪声错误标志位
USART_FLAG_FE帧错误标志位
USART_FLAG_PE奇偶错误标志位

串口发送一个字符代码:

USART_SendData(USART1,'o');
//USART_GetFlagStatus用来判断是否发送完成标志
while (USART_GetFlagStatus( USART1, USART_FLAG_TXE) == RESET );

封装一个发送字符的函数:

void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)
{
    USART_SendData(USARTx,Data);
   while (USART_GetFlagStatus( USART1, USART_FLAG_TXE) == RESET );

}

封装一个发送字符串的函数:

void USART_SendStr(USART_TypeDef* USARTx,char *str)
{
     uint16_t i = 0;
	 do
	 {
		 USART_SendByte(USARTx,*(str+i));
		 i++;
	}while(*(str+i) != '\0');
	while (USART_GetFlagStatus( USART1, USART_FLAG_TC ) == RESET );
}

三、串口中断接收配置

void Usart_Init(void)
{ 
//定义串口中断结构体
NVIC_InitTypeDef  nvic_usartStruct;
//初始化中断优先组2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//初始化外部中断源
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//中断结构体定义
nvic_usartStruct.NVIC_IRQChannel    = USART1_IRQn;
nvic_usartStruct.NVIC_IRQChannelCmd = ENABLE;
nvic_usartStruct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_usartStruct.NVIC_IRQChannelSubPriority = 1;
//初始化中断结构体
NVIC_Init(&nvic_usartStruct);
}

最终串口收发配置程序:

void Usart_Init(void)
{ 
 //定义引脚结构体
 GPIO_InitTypeDef gpio_initStruct; 
 //定义串口结构体
 USART_InitTypeDef usart_initStruct;
 //定义串口中断结构体
 NVIC_InitTypeDef  nvic_usartStruct;

//使能GPIO口的时钟、串口时钟、引脚复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

//配置GPIOA9 TX 复用功能推挽输出模式GPIO_Mode_AF_PP
gpio_initStruct.GPIO_Mode   = GPIO_Mode_AF_PP;
gpio_initStruct.GPIO_Pin    = GPIO_Pin_9;
gpio_initStruct.GPIO_Speed  = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &gpio_initStruct);
//配置GPIOA10  RX  浮空输入模式GPIO_Mode_IN_FLOATING
gpio_initStruct.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
gpio_initStruct.GPIO_Pin    = GPIO_Pin_10;
GPIO_Init(GPIOA, &gpio_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);
//使能串口
USART_Cmd(USART1, ENABLE);

//初始化中断优先级组2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//初始化外部中断源
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

//中断结构体配置
nvic_usartStruct.NVIC_IRQChannel    = USART1_IRQn;
nvic_usartStruct.NVIC_IRQChannelCmd = ENABLE;
nvic_usartStruct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_usartStruct.NVIC_IRQChannelSubPriority = 1;
//初始化中断结构体
NVIC_Init(&nvic_usartStruct);

}

四、中断处理函数编写

void USART1_IRQHandler(void)
{  
	  char date;
    //判断串口标志位是否产生中断,开始接收数据
	  if ( USART_GetITStatus(USART1, USART_IT_RXNE) != RESET )
	  {     //获取串口信息
		    date = USART_ReceiveData(USART1);		
		    if(date == 'O')
			{
				   GPIO_ResetBits(GPIOC, GPIO_Pin_13);
		           USART_SendStr(USART1,"led is open");
			}						  
		}         
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值