工程师 - Raspberry Pi Pico程序:读取SPI数据后从串口输出

1,通过Arduino IDE编写代码,并使用Pico C SDK。编译后烧写到Pico板卡中。

使用SPI1,端子号为GPIO 10, 12, 13, 15.

SPI的波特率为400K。

UART设置为500K。

2,第一个版本,将数据以16bit单位的十进制数值形式打印出来

SPI读取单位为2个字节,长度为8.

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "pico/stdlib.h" #include "hardware/spi.h" #include <stdio.h> #include "hardware/irq.h" #include "hardware/structs/spi.h" #include "hardware/resets.h" void setup() { Serial.begin(500000); gpio_set_function(10, GPIO_FUNC_SPI); gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(15, GPIO_FUNC_SPI); spi_init(spi1, 400000); spi_set_format(spi1,16,SPI_CPOL_1,SPI_CPHA_1,SPI_MSB_FIRST); spi_set_slave(spi1, 1); irq_set_exclusive_handler(SPI1_IRQ, my_spi_handler); irq_set_enabled(SPI1_IRQ, true); irq_set_priority(SPI1_IRQ,0); spi1_hw->imsc = 1 << 2; } uint16_t recvBuff[8]; volatile bool recvBuffReady = false; void my_spi_handler() { spi_read16_blocking(spi1, 0, recvBuff, 8); recvBuffReady = true; } void loop() { if (recvBuffReady) { recvBuffReady = false; for (int i = 0; i < 8; i++) { Serial.print(recvBuff[i]); Serial.printf(","); } Serial.println(); } } |

2,修改一下输出格式。

第一个版本的工作情况,master发送是16x2个字节发送一次。Pico板作为slave,是8x2读取一次,把数据存下来。

输入的二进制数据格式,输出时,每2个字节作为一个数值打印成十进制格式,会比较长。

然后loop里面把一次读取的再发出去。读取发送的节奏是可控的,发一次,读两次,正好。

而如果Master连续发送数据的话,这个程序运行状态就不一样了。发送读取节奏不一致了,一次读满8个字节,可能会超时。

而且我们要输出的主要是连续的可打印的字符串,输出每个字符调用write函数即可。

第二个版本的修改,SPI读取单位改为1个字节,长度为8.

串口输出改为write函数。

不过发现有些数据是乱码,或者会丢失。

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "pico/stdlib.h" #include "hardware/spi.h" #include <stdio.h> #include "hardware/irq.h" #include "hardware/structs/spi.h" #include "hardware/resets.h" void setup() { Serial.begin(500000); gpio_set_function(10, GPIO_FUNC_SPI); gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(15, GPIO_FUNC_SPI); spi_init(spi1, 400000); spi_set_format(spi1,8,SPI_CPOL_1,SPI_CPHA_1,SPI_MSB_FIRST); spi_set_slave(spi1, 1); irq_set_exclusive_handler(SPI1_IRQ, my_spi_handler); irq_set_enabled(SPI1_IRQ, true); irq_set_priority(SPI1_IRQ,0); spi1_hw->imsc = 1 << 2; } uint8_t recvBuff[8]; volatile bool recvBuffReady = false; void my_spi_handler() { spi_read_blocking(spi1, 0, recvBuff, 8); recvBuffReady = true; } void loop() { if (recvBuffReady) { recvBuffReady = false; for (int i = 0; i < 8; i++) { Serial.write(recvBuff[i]); } } } |

3,使用中断发送数据。

试验了下,开始传输是OK的,发了几十个字节之后就不好用了。

有可能是在中断里调用串口的写操作会引发不可知的影响。

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "pico/stdlib.h" #include "hardware/spi.h" #include <stdio.h> #include "hardware/irq.h" #include "hardware/structs/spi.h" #include "hardware/resets.h" void setup() { Serial.begin(500000); gpio_set_function(10, GPIO_FUNC_SPI); gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(15, GPIO_FUNC_SPI); spi_init(spi1, 400000); spi_set_format(spi1,8,SPI_CPOL_1,SPI_CPHA_1,SPI_MSB_FIRST); spi_set_slave(spi1, 1); irq_set_exclusive_handler(SPI1_IRQ, my_spi_handler); irq_set_enabled(SPI1_IRQ, true); irq_set_priority(SPI1_IRQ,0); } uint8_t recvBuff[5]; void my_spi_handler() { spi_read16_blocking(spi1, 0, recvBuff, 1); Serial.write(recvBuff[0]); } void loop() { } |

4,直接在loop里通过中断设置flag,或者判断是否数据可读,来收取数据,都没有输出。

这个是因为时序控制不对,中断里你不读数据,到了loop里就来不及了,读不到了把。

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "pico/stdlib.h" #include "hardware/spi.h" #include <stdio.h> #include "hardware/irq.h" #include "hardware/structs/spi.h" #include "hardware/resets.h" bool flag_readable; uint8_t recvBuff[5]; void setup() { Serial.begin(500000); gpio_set_function(10, GPIO_FUNC_SPI); gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(15, GPIO_FUNC_SPI); spi_init(spi1, 400000); spi_set_format(spi1,8,SPI_CPOL_1,SPI_CPHA_1,SPI_MSB_FIRST); spi_set_slave(spi1, 1); irq_set_exclusive_handler(SPI1_IRQ, my_spi_handler); irq_set_enabled(SPI1_IRQ, true); irq_set_priority(SPI1_IRQ,0); spi1_hw->imsc = 1 << 2; flag_readable = false; } void my_spi_handler() { flag_readable = true; } void loop() { if(spi_is_readable(spi1)){ flag_readable = false; spi_read_blocking(spi1, 0, recvBuff, 1); Serial.write(recvBuff[0]); } } |

5,使用ringbuffer函数来读取数据,然后loop里进行发送。

Ring Buffer里的buffer大小是250,这里使用大小100的buffer去读取,然后输出。

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "pico/stdlib.h" #include "hardware/spi.h" #include <stdio.h> #include "hardware/irq.h" #include "hardware/structs/spi.h" #include "hardware/resets.h" #include "ringbuffer.h" RingBuffer rb; #define BUF_LEN 100 uint8_t buffer[BUF_LEN]; void setup() { Serial.begin(500000); gpio_set_function(10, GPIO_FUNC_SPI); gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(15, GPIO_FUNC_SPI); spi_init(spi1, 400000); spi_set_format(spi1,8,SPI_CPOL_1,SPI_CPHA_1,SPI_MSB_FIRST); spi_set_slave(spi1, 1); irq_set_exclusive_handler(SPI1_IRQ, my_spi_handler); irq_set_enabled(SPI1_IRQ, true); irq_set_priority(SPI1_IRQ,0); // Enable receive FIFO half full and receive FIFO read timeout interrupt spi1_hw->imsc = 1 | (1 << 2); RingBuffer_Init(&rb); } void my_spi_handler() { uint8_t data; // Clear the receive FIFO read timeout interrupt status if(spi1_hw->ris | SPI_SSPRIS_RTRIS_BITS){ spi1_hw->icr = SPI_SSPICR_BITS; } while(spi_is_readable(spi1)){ spi_read_blocking(spi1, 0, &data, 1); RingBuffer_Write(&rb, &data, 1); } } void loop() { uint16_t len = RingBuffer_GetDataLength(&rb); uint8_t data; if (len > 0) { if(len > BUF_LEN) len = BUF_LEN; RingBuffer_Read(&rb, buffer, len); Serial.write(buffer, len); } else{ /* If receive fifo is not empty, read the data */ if(spi1_hw->sr | SPI_SSPSR_RNE_BITS){ if(spi_is_readable(spi1)){ spi_read_blocking(spi1, 0, &data, 1); RingBuffer_Write(&rb, &data, 1); } } } } |

备注:

1,接SPI信号线来抓取SPI数据,两边的地线最好也能接到一起,不然信号还是有些不稳定的。比如在没有通信时,还是会打印出乱码数据。

就这种:�����

相关推荐
koo3643 小时前
李宏毅机器学习笔记16
人工智能·笔记·机器学习
丰锋ff4 小时前
2007 年真题配套词汇单词笔记(考研真相)
笔记·学习·考研
聪明的笨猪猪5 小时前
Java “并发容器框架(Fork/Join)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Wils0nEdwards10 小时前
tex 写的论文如何统计字数
笔记
小秋学嵌入式-不读研版10 小时前
C49-函数指针(通过指针调用函数)
c语言·笔记
Larry_Yanan12 小时前
QML学习笔记(二十四)QML的Keys附加属性
c++·笔记·qt·学习·ui
nnerddboy12 小时前
FPGA自学笔记(正点原子ZYNQ7020):1.Vivado软件安装与点灯
笔记·fpga开发
Chunyyyen12 小时前
【第十六周】自然语言处理的学习笔记01
笔记·学习·自然语言处理
我命由我1234512 小时前
Photoshop - Photoshop 工具栏(5)多边套索工具
笔记·学习·ui·职场和发展·photoshop·ps·美工