三种通信总线的前世今生对比

本文介绍了嵌入式开发中常见的三种通信总线UART、SPI和I2C,包括各自的特点和应用场景。UART作为通用外设,常用于开发调试;SPI是高速全双工串行总线,适用于多设备连接;I2C则是低速、双向通信总线,适合于主从结构。文章通过代码示例展示了如何在STM32中配置这些通信接口,并讨论了它们的数据传输方式和模式选择。

                                                  人生中的第一篇偏技术的文章    

     这两年主要从事嵌入式应用层的开发,对驱动层了解的不是很透彻,第一篇文章也不知道该写点神魔,那就从几个常用的通信总线开始吧,一方面算是给自己的学习经历添点痕迹(也算是重新学习的过程),二是以后回顾知识点也有个熟悉的资料,方便查阅。以后的内容有自己的想法(可能不对,还请指正,我尽量多查看一下书籍,争取总结正确),也会引用别人的一些见解,我尽量标明出处(链接),防止我断章取义,好让同志们(也可能就我自己看而已,假设有别人浏览吧)查找内容的源头。不BB了,是骡子是马拉出来遛遛吧。

STM32中几种通信方式的区别:

1.UART(USART)

2.IIC总线

3.SPI总线

 

主要参考博客:https://blog.youkuaiyun.com/oqqHuTu12345678/article/details/65445338?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

对博主表示感谢。

UART、SPI、I2C对比

UART、SPI、I2C对比表格
对比项          UART                      SPI             I2C
信号线数目 3根,RX、TX、GND 4根,SDO、SDI、SCLK、SS 2根,SDA、SCLK
设备从属关系            —— 存在主从设备。SPI用片选信号选择从机  存在主从设备。IIC用地址选择从机。
通信方式 全双工通信 全双工通信 半双工通信
通信速率 速度慢 比I2C总线要快,速度可达到几Mbps I2C的速度比SPI慢
应用领域

1、UART常用于控制计算机与串行设备的芯片

2、就是我们经常所说的串口,基本都用于调试。

主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间 I2C一般是用在同一个板子上的2个IC之间的通信 ,它可以替代标准的并行总线,连接各种集成电路和功能模块。
传输距离     I2C需要有双向IO的支持,而且使用上拉电阻,抗干扰能力较弱,一般用于同一板卡上芯片之间的通信,较少用于远距离通信
通信特征 异步,一帧可以传5/6/7/8位 同步,SPI允许数据一位一位的传送,甚至允许暂停。从最高位开始传。 同步,电平信号,一次连续8bit。从最高位开始传
协议复杂度 结构比较复杂 SPI实现要比UART简单,UART需要固定的波特率,就是说两位数据的间隔要相等,而SPI则无所谓,因为它是有时钟的协议。 协议比SPI复杂,但是连线比标准的SPI要少
对比  

在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。

在多个从器件的系统中,每个从器件需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

 

USART简介:通用同步异步收发器,全双工数据交换,UART,异步通信,为常用外设,用作开发调试。

代码如下:

 /**
  * @brief  USART GPIO 配置,工作参数配置
  * @param  无
  * @retval 无
  */
void USART_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 打开串口GPIO的时钟
    DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
    
    // 打开串口外设的时钟
    DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

    // 将USART Tx的GPIO配置为推挽复用模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
    
    // 配置串口的工作参数
    // 配置波特率
    USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
    // 配置 针数据字长
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    // 配置停止位
    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(DEBUG_USARTx, &USART_InitStructure);
    
    // 串口中断优先级配置
    NVIC_Configuration();
    
    // 使能串口接收中断
    USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);    
    
    // 使能串口
    USART_Cmd(DEBUG_USARTx, ENABLE);        
}

/**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
 
  /* 嵌套向量中断控制器组选择 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  /* 抢断优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}

// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
  uint8_t ucTemp;
    if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
    {        
        buffer[num] = USART_ReceiveData(DEBUG_USARTx);
   // USART_SendData(DEBUG_USARTx,buffer[num]);
        num ++;
        
        if(num==10)
        {
            for(num=0;num<10;num++)
            {
                Delay(20);//在发送两个数据的间隙需要一定的时间。
                Usart_SendByte(DEBUG_USARTx,buffer[num]);
                Delay(20);
            }
            num = 0;
        }
    }    
}

uint16_t USART_ReceiveData(USART_TypeDef* USARTx)//串口接收数据函数,直接读取的USART的数据寄存器。
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
 
  /* Receive Data */
  return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}

/*****************  发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
    /* 发送一个字节数据到USART */
    USART_SendData(pUSARTx,ch);
        
    /* 等待发送数据寄存器为空 */
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);    
}

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_DATA(Data));
    
  /* Transmit Data */
  USARTx->DR = (Data & (uint16_t)0x01FF);
}

串口也就这些东西,自从有了固件库,开发就变得很容易了,只要懂得原理,代码不需要写太多,只要将一些问题想全面,考虑上一些特殊的情况,软件上做一些保护尽量避免发生问题。

SPI简介:高速全双工的串行总线。

(1)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值