单片机学习小组
直播中

听我讲

10年用户 737经验值
擅长:电源/新能源 MEMS/传感技术
私信 关注

数据的通信方式/同步方式有哪几种?

数据的通信方式有哪几种?
数据的同步方式有哪几种?

回帖(1)

李亚祎

2022-2-28 15:29:11
一、数据的传送方式


1.串行通信


速度慢,但占用资源少,按顺序传输、逐个位传输,(使用一个数据线就能解决传输问题,即一个I/O口就可以解决问题)

2.并行通信


速度快,但占用资源多,各个位同时传输、多位传输,(多少位数据就需要多少根数据线)

适用于:USART,IIC,SPI



二、数据的通信方式


1、单工通信 iic,spi


A发--单向通道--B收



2、半双工通信 spi


A发--双向通道--B收 / B发--双向通道--A收

(同一时刻时,一个设备发送时,另一个就不能同时进行发送)



3、全双工通信 usart,spi


A发、B发--双向通道--B收、A收

(两个设备在同一时刻都可以进行收发数据,传输)



三、数据的同步方式


【同步 & 异步】

1、同步通信


①数据传送以数据块(多个字符组成的)的形式的;在数据块内,字符与字符间无间隔

②接收与发送时钟严格同步,有同步时钟SCLK

③通信双方的各自的两个时钟SCLK是连在一起的,提供同步时钟;接受与发送是同步的

2、异步通信


①没有时钟线SCLK的约束,因此有了②

②在发送数据之前发送一个起始位, 发送奇偶检验位+想要发送的字符,最后发送停止位



比较  有无时钟SCLK的约束






四、数据的通信速率


1、比特率(在IIC,SPI中使用)Bitrate


每秒传输的二进制位,bit/s

2、波特率(在串口中使用)Baudrate


每秒传输的码元个数

一个二进制位表示一个码元





五、串口通信


TTL电平:数字芯片的电平,单片机使用,0-5V

232电平:电脑串口的电平,工业电平,-3-15V

原生串口通信:直接设备与传感器连接  (eg. GPS模块,WiFi模块...)

1、串口数据包的基本组成




起始位:逻辑0  (第一个低电平)

停止位:逻辑0.5/1/1.5  (高电平)  可以达到校准同步时钟的目的

有效数据位:

校验位:

            校验方法有:

                                  奇校验:有效数据+校验位中的“1”个数为奇数;   即如:10010110,有四个1了,校验位加上一个1,凑5个,为奇校验 (九个位传输)

                                  偶校验:有效数据+校验位中的“1”个数为偶数;   即如:10010110,有四个1了,校验位加上一个0,不加1保持4个1不变,为偶校验  (九个位传输)

                                  0校验:校验位总为0

                                  1校验:校验位总为1

                                  无校验:数据不包含校验位



六、串口的结构体


1、串口通信


TX 发送(配置输出模式)   RX 接收(配置输入模式,浮空输入)



USART:同步异步收发器

UART  :异步收发器

↓ 在“中文参考手册” ↓

可以看出 USART1APB2总线下,其余在APB1总线下

APB2的频率与AHB系统总线的频率一样 (72*10的6次方 hz )

APB1  (32*10 6)



2、异步收发器的结构体的配置




  • uint32_t USART_BaudRate;     //波特率


         

波特率设置: (在APB2中是)使用固件库时直接设置  =115200 =72 *10(6次方)/16*USATDIV





  • uint16_t USART_WordLength;   //配置数据位的字长


         

有 8位 与 9位





  • uint16_t USART_StopBits;   //停止位


        

正常情况下使用 1 停止位





  • uint16_t USART_Parity;    //校验位的配置


         





  • uint16_t USART_Mode;    //模式的设置


         

USART_Mode_Rx | USART_Mode_Tx      即可 表示Rx输入Tx输出都可行



  • uint16_t USART_HardwareFlowControl;    //配置硬件流模式


         

一般情况下,不做选择



3、同步收发器的结构体配置


uint16_t USART_Clock;    //时钟配置




uint16_t USART_CPOL;    //极性  配置串口空闲为什么电平
uint16_t USART_CPHA;    //相位  配置选择边沿




1Edge 第一边沿 ≈ 上升沿

2Edge 第二边沿 ≈ 下降沿

uint16_t USART_LastBit;   //配置最后一位时钟,使能开关


4、常用函数









七、配置串口的发送与接收




  • 配置时钟:GPIO口的时钟,串口的时钟,引脚复用的时钟
  • 配置GPIO口+串口结构体
  • 串口的发送




1、串口接收字符


1、打开APB2下的GPIOA的时钟信号;因为UART1在APB2总线下

2、同时使能引脚复用时钟

3、打开UART1的时钟信号

4、【配置APB2下的GPIOA的结构体】 配置PA9串口---TX线---输出引脚

      Mode:推挽输出   

5、【配置APB2下的GPIOA的结构体】 配置PA10串口---RX线---输入引脚(接收)

     Mode:浮空输入

记得初始化结构体       stm32f10x_gpio.h

6、【配置串口的结构体】

BaudRate=115200;

Mode=USART_Mode_Rx | USART_Mode_Tx;

记得初始化结构体 + 使能串口 USART_Cmd()      stm32f10x_uart.h

#include "stm32f10x.h"
#include "usart.h"

void usart_demo(void)
{
        GPIO_InitTypeDef  GPIOinitStruct;
        USART_InitTypeDef USARTinitStruct;
      
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

        //PA9
        GPIOinitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIOinitStruct.GPIO_Pin=GPIO_Pin_9;
        GPIOinitStruct.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIOinitStruct);

        //PA10
        GPIOinitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIOinitStruct.GPIO_Pin=GPIO_Pin_10;
        GPIO_Init(GPIOA, &GPIOinitStruct);
      
        //串口配置
        USARTinitStruct.USART_BaudRate=115200;
        USARTinitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
        USARTinitStruct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
        USARTinitStruct.USART_Parity=USART_Parity_No;
        USARTinitStruct.USART_StopBits=USART_StopBits_1;
        USARTinitStruct.USART_WordLength=USART_WordLength_8b;
        USART_Init(USART1, &USARTinitStruct);
        USART_Cmd(USART1,ENABLE);      
}




2、主函数


int main()
{
        USART_SendData(USART1, 'X');//发送字符函数
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//判断串口状态函数
        USART_SendData(USART1, 'Y');
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
        USART_SendData(USART1, 'n');
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
    delay(1000);
}

USART_FLAG_TXE  发送空标志位定义;判断当串口的状态是空的时候,即字符发送完毕的时候;执行下一个字符的发送



3、串口接收字符串


在接收字符的基础上,封装2个函数,实现达到字符串输出的目的



封装一个输出单个字符的函数

void USART_SendByte(USART_TypeDef* USARTx, uint16_t data)
{
        USART_SendData(USARTx, data);
        while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
}
封装一个输出字符串的函数

void USART_SendStr(USART_TypeDef* USARTx, char *str)//字符串以指针的形成存入
{
        uint16_t i=0;
        do
        {
                USART_SendByte(USARTx, *(str + i));       //利用i++逐个通过字符函数进行输出
                i++;
        }
        while(*(str + i) != '');                   //字符串的最后一个字符是‘’,以此为结束标志
      
        while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);  //检查发送完成标志位
      
      
}


   在使用串口接收字符串时,字符串函数不能直接调用 库里面的输出字符函数USART_SendData ;

   否则只会发送字符串的最后一个字符;

   所以只能通过封装一个发送字符串的函数,调用USART_SendData,对字符串里面的字符一个一个的进行调用





















举报

更多回帖

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