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

就这种:�����

相关推荐
清风一徐2 小时前
禅道从18.3升级到21.7.6版本
笔记
Jack___Xue2 小时前
LangChain实战快速入门笔记(六)--LangChain使用之Agent
笔记·langchain·unix
零度@3 小时前
SQL 调优全解:从 20 秒到 200 ms 的 6 步实战笔记(附脚本)
数据库·笔记·sql
im_AMBER3 小时前
Leetcode 78 识别数组中的最大异常值 | 镜像对之间最小绝对距离
笔记·学习·算法·leetcode
其美杰布-富贵-李4 小时前
HDF5文件学习笔记
数据结构·笔记·学习
d111111111d5 小时前
在STM32函数指针是什么,怎么使用还有典型应用场景。
笔记·stm32·单片机·嵌入式硬件·学习·算法
静小谢6 小时前
前后台一起部署,vite配置笔记base\build
前端·javascript·笔记
ask_baidu6 小时前
Doris笔记
android·笔记
IMPYLH7 小时前
Lua 的 IO (输入/输出)模块
开发语言·笔记·后端·lua
2301_783360137 小时前
【学习笔记】关于RNA_seq和Ribo_seq技术的对比和BAM生成
笔记·学习