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

就这种:�����

相关推荐
lkbhua莱克瓦2430 分钟前
Java基础——常用API2
java·笔记·github·学习方法
丰锋ff1 小时前
英一2016年真题学习笔记
笔记·学习
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记
新子y1 小时前
【小白笔记】稀疏数组 (Sparse Array) 在计算机科学中的存储优化问题
笔记
摇滚侠1 小时前
Spring Boot3零基础教程,Lambda 表达式的使用,笔记96
spring boot·笔记
charlie1145141912 小时前
HTML 理论系统笔记2
前端·笔记·学习·html·基础·1024程序员节·原生
Elias不吃糖3 小时前
Linux 环境适应 Day 1 全面笔记
linux·c++·笔记
爱奥尼欧3 小时前
【Linux笔记】网络部分——传输层协议TCP(1)
linux·运维·网络·笔记·tcp/ip·1024程序员节
Lester_11013 小时前
嵌入式学习笔记 - 用泰勒公式解决 tanh函数
笔记·学习·算法
sunshine~~~3 小时前
【笔记】macOs arm架构安装虚拟机Ubuntu环境:ROS2 + Python开发
arm开发·笔记·python·macos·ros2