串口协议


USART串口通信

stm32中使用USART串口通信主要通过RX和TX两个接口完成基础操作,发送的数据通过总线到发送数据寄存器TDR,然后TDR中数据会发送到发送移位寄存器,发送移位寄存器会将比特右移的传到USARTX_TX引脚,产生串口协议规定的波形,当数据从发送移位寄存器发送完成时,TXE标志位会置1,只需判断TXE就可以知道是否可以传下一个数据

同样在接受控制器中通过USARTX_TX引脚接受数据,接受完成会将RXNE标志位置1

在实际使用中只有DR寄存器可供读写,写入DR时,数据走TX发送,读出DR时,数据走TX接受。

发送数据的函数形式为

void Serial_SendChar(uint8_t ch)
{
    
  // 发送字符
  USART_SendData(USART1, ch);
  // 等待发送缓冲区为空  发送完成会将USART_FLAG_TXE置1
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

接受数据的形式为

if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  {
    // 读取接收到的数据
    uint8_t RxData = USART_ReceiveData(USART1);
    
    //do something...
    
    //清除接收中断标志位
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  }
波特率计算公式

$$
波特率=f_{PCLK2或1}/(16*DIV)
$$

发送器和接收器的波特率由波特率寄存器BRR里的DIV确定。

例:

若频率$f_{PCLK1}=72MHz$,波特率为9600,代入上式,解得$DIV=72MHz/9600/16=468.75$转为十六进制为0x01D4.CH

USARTX串口初始化(例子中采用USART1端口)
void Serial_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure; // 定义 GPIO 初始化结构体
  USART_InitTypeDef USART_InitStructure; // 定义 USART 初始化结构体

  // 使能 GPIOA 和 USART1 的时钟(改成对应端口)
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

  // 配置 GPIOA 的引脚 9 为复用推挽输出(改成对应端口)
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // 配置 GPIOA 的引脚 10 为浮空输入(改成对应端口)
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // 配置 USART 初始化结构体
  USART_InitStructure.USART_BaudRate = 9600; // 波特率为 9600
  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; // 支持接收和发送

  // 初始化 USART1
  USART_Init(USART1, &USART_InitStructure);
  // 使能 USART1
  USART_Cmd(USART1, ENABLE);
}

I2C通信

I2C有两根通信线:SCL(Serial Clock),SDA(Serial Data),支持同步,半双工通信,支持总线挂载多设备(一主多从,多主多从)

设备的SCL和SDA均要配置程开漏输出模式,且SCL和SDA需各添加一个上拉电阻,阻值一般为4.7kΩ左右。

I2C时序基本单元

I2C总线进行通信的起始条件是SCL高电平期间,SDA从高电平转换到低电平,如下图所示。

终止条件是SDA从低电平转换到高电平,SCL处于高电平。

I2C发送数据:在SCL低电平期间,发送端将数据位依次按高位到低位放到SDA线上,然后由接收端在SCL高电平期间读取数据位。(若主机为接受端,需要在主机接受数据之前释放SDA,即相对于切换为输入模式)

在应答时候SCL处于高电平时,SDA应处于低电平表示收到应答信号。第一个发送字节通常都是主机寻找从机地址。

软件实现
  • 初始化(以stm32f103c8t6芯片的引脚为例,可知PB10是I2C_SCL的引脚,PB11是I2C_SDA的引脚)

void MyI2C_Init(void)
{
    // 使能 I2C1 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    // 使能 GPIOB 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 配置 GPIOB 的引脚 10 和 11 为开漏输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SCL_PORT, &GPIO_InitStructure);

    GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11); // 设置 PB10 和 PB11 为高电平
    
}

文章作者: LsWorld
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LsWorld !
评论
  目录