这可以说是三个最常用的通信外设,他们的本质都一样,发送字节(这不是废话,以太网也是发送字节啊,只不过有规范.),他们只需要暴漏几个函数,读/写以及其他辅助函数,例如初始化/中断.
I2C技术参数:
- 主从模式 (默认主机,从机地址0x55,主机支持10B寻址)
- 标准(100kHz),快速(400kHz),快速Plus(1MHz)
- 自带收发缓冲区 (深度各16个元素)
- DMA/IRQ (正常标配)
- Synopsys IP (买的牛逼IP,树莓派没设计.)
SPI技术参数:
- 硬件CS支持 (主机从机都可以用)
- 分布到芯片的很多引脚上 (看Pinout就知道)
- 支持多种SPI模式 (TI/NI/摩托罗拉)
- 自带FIFO (深度8 * 32B)
- 支持4B - 16B传输帧 (但是需要考虑FIFO问题)
- DMA/IRQ/突发传输支持 (正常标配)
- 可以用作从机 (但是没有例子)
- 频率支持(主机):Fperi/65024 ~ Fperi/2 (在标准125MHz下,即约2kHz到约75MHz)
- 频率支持(从机):Fper/65024 ~ Fperi/12 (在标准125MHz下,即约12kHz到约75MHz)
- 2组SPI (都可以自由用)
- PL022 公版IP (ARM白送IP,树莓派自己没设计.)
UART技术参数:
- 硬件流控 (CTS,RTS,官方图片没有写,实际有引出.)
- 自带FIFO (TX深度:8 * 32B,RX深度:12 * 32B)
- 可编程波特率:Fperi/1048560 ~ Fperi/16 (在标准125MHz下,即约120bps ~ 7812Kbps)
- 可编程位数 (5,6,7,8 BIT + 1,2 STOP)
- 2组UART (UART0通常用于stdio,UART1可以自由使用.)
- DMA/IRQ (正常标配)
- PL011 公版IP (ARM白送IP,树莓派自己没设计.)
I2C软件上可以防止因为无设备的锁死,但是如果发生其他类型的锁死,还得使用防锁死的函数,但是要解决锁死状态,需要重置IO状态信息.其关键函数如下,其中nostop如果为true,则不发送stop,用于restart很有用.
- int i2c_write_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop);
- int i2c_read_blocking(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop);
SPI基本测试代码:
int main() {
uint8_t buf1 = 0xAA;
uint8_t buf2[2] = {0xA5,0x5A};
spi_init(spi0, 1000 * 1000);
spi_set_format(spi0,8,SPI_CPOL_0,SPI_CPHA_0,SPI_MSB_FIRST);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
gpio_set_function(PIN_CS,GPIO_FUNC_SPI);
for(;;){
sleep_ms(5);
spi_write_blocking(spi0, &buf1, 1);
sleep_ms(5);
spi_write_blocking(spi0, buf2, 2);
}
return 0;
}
另外由于FRF是没有函数设置的,所以我们要手动设置.
hw_write_masked(&spi_get_hw(spi0)->cr0,0 << SPI_SSPCR0_FRF_LSB,SPI_SSPCR0_FRF_BITS);
默认受硬件CS时候,时序结果是这样的.(不同FRF不同,具体参考手册.)
如果需要一个CS下连续发送数据,那么还要人工操作CS,但其实依然做不到最大带宽,感觉是设计缺陷.
UART本身配置在例子里面已经说的很清楚,如果我们要阻塞发送一个字节可以用uart_putc_raw函数来完成,另外读取函数都没有超时控制,所以要自己处理好.
OK,之前已经把所有的主机模式都说了,UART不分主从,因为这里没寻址模式,I2C和SPI都分,I2C部分的从机描述,从手册4.3.10.1.2开始,SPI部分的从机描述从4.4.3.15开始,由于SDK还没完善,现在只能用标志位判断各种先写着了.