STM32
直播中

小香干

12年用户 516经验值
擅长:399938
私信 关注
[问答]

串口中断的实际操作是怎样的?

串口通信有哪些类型?
串口中断的实际操作是怎样的?

回帖(1)

姚远

2021-12-16 13:55:14
   一.基础知识

  1.串口通信的分类

  因为同步的是不管什么直接发送,通过一条时钟线来确定数据的先后关系,保持它的有序性。而异步则是一个一个的发送,不用时间线来确定数据的有序性。
  所以:同步带时钟信号线,如SPI、IIC。异步不带时钟信号线,如UART。
  搬出官方的一张表:
  
通信标准
引脚说明
通信方式
通信方向
  UART
(通用异步收发器)
TXD:发送端
RXD:接受端
GND:公共地
异步通信
全双工
  单总线
(1-wire)
DQ:发送/接受端
异步通信
半双工
SPI
SCK:同步时钟
MISO:主机输入,从机输出
MOSI:主机输出,从机输入
同步通信
全双工
I2C
SCL:同步时钟
SDA:数据输入/输出端
同步通信
半双工
2.中断的优先级

  32的中断具有分级,以便管理。其有两个优先级:抢占优先级 & 响应优先级。抢占优先级>响应优先级,0~4的优先级,0最大,4最小。在SCB->AIRCR中配置(反正我还是不会配置)。

二.实例操作
1.中断的配置
中断的配置,需要遵循:先分组,再设置优先级


分组:(不知道为什么,默认分组2就可以了)


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
设置:


NVIC_InitTypeDef   NVIC_InitStructure;    //定义结构体

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//中断通道选择,我也不知道有哪些参数。串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;// 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能通道的设置,我也不知道。IRQ通道使能

NVIC_Init(&NVIC_InitStructure);        //根据上面指定的参数初始化NVIC寄存器
2.串口的配置
在正点原子的开发板里面提供了串口的配置文件Urat.c


如同官方PPT的内容:


①串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();
②串口复位:USART_DeInit(); 这一步不是必须的
③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF_PP
④串口参数初始化:USART_Init();
⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
      NVIC_Init();
      USART_ITConfig();
⑥使能串口:USART_Cmd();
⑦编写中断处理函数:USARTx_IRQHandler();


void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟

  //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

  //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 初始化设置
  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

}
3.串口中断的实际操作:
void USART1_IRQHandler(void)                        //串口1中断服务程序
if(USART_GetITStatus(USART1, USART_IT_RXNE)
{这里面放置串口成功接收的代码}

u8 USART_ReceiveData(USART1); //这是一个读取缓存数据的代码
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待发送完成
USART_SendData(USART1,u8) //这是发送数据的代码
或者可以通过直接使用Usart库里面的通信协议,采用Usart.c的文件进行串口访问。其协议是文本的结束符为0x0D和0x0A


  

  

  然后需要配置新的管脚,原管脚可以不用配置。并添加新的代码,故串口的配置可以将上文中的代码全部复制,然后更改管脚为映射后的管脚,然后添加:

重映射IO口时钟使能:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
重映射开启:


GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
快捷模板:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
举报

更多回帖

发帖
×
20
完善资料,
赚取积分