您的位置:首页 > 其它

串口和通信

2019-07-11 23:31 80 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_41382643/article/details/95519615

串口和通信应该是学到现在最难的部分了,也可以说是无人机工程中非常关键的一部分,因为要涉及到各个模块的通信,每个模块的代码都巨长无比。。。
而想要准确地使用各个模块,通信协议无疑要掌握的较为细致。

首先总结一下所学,常用的串行通信方式有UART、SPI和IIC
UART利用单片机自带的串口模块和IO口进行通信,比较简单(算是),但是多用于两机通信,比如单片机和电脑,好像不常用于对模块的读取。

IIC在stm32中见过,一般是用软件模拟的,在库函数中编写需要的起始信号、应答信号、发送和接受等等,然后调用库函数即可。

SPI也学过一点,算是同步通信吧,利用时钟驱动两个串行移位寄存器,收和发同时进行,如果要发就直接发,要收就发空字节然后读SPI寄存器。

但实际上也不算学过,因为具体的过程还是一知半解,只会copy手把手教学的例程里的库函数,根本不了解原理,结果在msp430使用中,没有现成的库函数之后就一脸懵比,给的例程都看不懂在干嘛,非常的绝望。

这次想要把这几种通信协议的时序详细分析一下,因为STM32的代码和讲解都很详细,就从这个开始看起,因为原理肯定是一样的,然后试着读一下msp430的例程代码,实现移植。。。

1、UART的标准库代码

USART_InitStructure.USART_BaudRate = bound;
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(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);

注释复制不过来,不过直接看英文的意思也知道在干什么,设置波特率、8位、1个停止位、无奇偶校验、无硬件数据流控制(这里不知道是啥)、模式设为收发。然后对模块进行配置、使能接收中断,然后使能模块。

对于收发的使用:
一般使能接收中断,因为你不知道数据何时会发过来。串口的硬件实际上是数据自动接收的,接受一个字节后,也就是缓冲器满,会引起接收中断,在中断中使用如下函数:

Res =USART_ReceiveData(USART1);

但这并不是接收过程,因为接收过程已经完成了,数据已经在寄存器里了,这个函数只是将接收寄存器中的值读出来。
如果想要发送数据,用这个函数:

USART_SendData(USART1, USART_RX_BUF[t]);

严格来讲这也不能算是发送过程,因为这实际上是写缓冲寄存器的一步操作,硬件在发送缓冲器被写入数据后会自动进行发送,可以说这是两步,串行发送这一步紧接着写寄存器后面进行。这就是UART的时序了。

对于MSP430用寄存器编程的实现,可以理解为将串口配置寄存器配置好,然后使能,开启中断,如果有接收中断那就是接收到了数据,在中断服务函数里保存起来,也就是读接收缓冲器,如果想要发送数据,就把数据写入发送缓冲器,同时利用标志位来判断发送是否完成,也就是刚刚说的第二步是否完成。

二、SPI通信

SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。
同步很关键,因为看图发现spi时钟发生器是收发双方移位寄存器共用的时钟。

所以spi收发是同一个过程,写缓冲器之后,实际上是进行了数据交换,因此可以发现接收数据也是一个主动的过程,不同于上述的uart。

再看一下配置代码:

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);

SPI_Cmd(SPI2, ENABLE);
SPI2_ReadWriteByte(0xff);

太长了根本不想看(实际上是根本看不懂),但是配置选项这么多,也侧面说明功能很强大吧。。。总之用默认设置一般就可以了我觉得。

对于读操作:

void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)
{
u16 i;
W25QXX_CS=0;
SPI2_ReadWriteByte(W25X_ReadData);
SPI2_ReadWriteByte((u8)((ReadAddr)>>16));
SPI2_ReadWriteByte((u8)((ReadAddr)>>8));
SPI2_ReadWriteByte((u8)ReadAddr);
for(i=0;i<NumByteToRead;i++)
{
pBuffer[i]=SPI2_ReadWriteByte(0XFF);
}
W25QXX_CS=1;
}

可以看出是先发送了读取命令(1次读写),然后发送要读数据的地址,这里的地址是3byte,(也就是3次读写,实际上地址是几位以及传输地址需要几次读写可能与模块有关?),之后的读写就都是模块在向单片机传输数据了。

对于写操作,例程还有个擦除。。。不知道什么鬼,具体下来再看,但实际上都是使用了那个基本的读写操作。

具体的函数为:

u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI2, TxData);
retry=0;

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI2);
}

算是比较简单易懂的吧,不多说了。

三、IIC

这个就很头大,既有软件模拟的,也有硬件的,虽然说硬件IIC并不常用,通常都是用软件模拟的,但5529就有硬件的IIC。。两种都了解一下吧。
这个东西难就难在对时序的理解要很到位,尤其是模拟IIC,虽然那些库函数大致知道是什么意思,但仔细分析一下,有一个比较清晰的了解还是有必要的。额,有点晚了,先到这里,明天再说。。。。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: