工程师 - 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 recvBuff8; 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(recvBuffi); 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 recvBuff8; 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(recvBuffi); } } } |

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 recvBuff5; void my_spi_handler() { spi_read16_blocking(spi1, 0, recvBuff, 1); Serial.write(recvBuff0); } 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 recvBuff5; 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(recvBuff0); } } |

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 bufferBUF_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数据,两边的地线最好也能接到一起,不然信号还是有些不稳定的。比如在没有通信时,还是会打印出乱码数据。

就这种:�����

相关推荐
软件技术NINI12 分钟前
盗墓笔记html+css+js 2页
css·笔记·html
智者知已应修善业41 分钟前
【用D触发器组成000-001-010-011-100】2025-6-7
驱动开发·经验分享·笔记·硬件架构·硬件工程
纪念 2291 小时前
数据库基础
数据库·笔记·学习方法
AnsonNie1 小时前
处理提示“wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。”【笔记】
笔记
山城码农笑松哥1 小时前
Redis 8.8 新特性实操笔记:原生数组、INCREX 限流、XNACK 流处理
redis·笔记·junit
xqqxqxxq1 小时前
SQL 字段约束笔记
android·笔记·sql
神龙天舞20013 小时前
CMake构建学习笔记-通用的CMake构建脚本
笔记·学习
Seven_Ting4 小时前
React-Hooks笔记
前端·笔记·react.js
AOwhisky4 小时前
Linux(CentOS)系统管理入门笔记(第二十一期)——防火墙管理(Firewalld)——zone、服务端口、富规则与端口转发
linux·运维·笔记·安全·centos·防火墙
腾飞开源4 小时前
01_K8s干货笔记之认识K8s
运维·笔记·云原生·容器·kubernetes·k8s·容器化部署