size_t 32/64平台下兼容的printf

本文介绍了如何在32位和64位系统中兼容地打印size_t类型变量的方法。针对不同位数系统下size_t定义的不同,推荐使用%Zd(GNU扩展)或%zd(C99标准)进行打印。

在32位下typedef unsigned int size_t,在64位下typedef unsigned long size_t。

 

如果需要printf size_t类型的变量,会出现32/64下不兼容的情况,此时可以使用%Zd或者%zd。%zd是C99规定的,%Zd是GNU的扩展。

#include "spi_slave_server.h" // spi #include <SPI.h> #include <ESP32SPISlave.h> #include "helper.h" ESP32SPISlave slave; // 创建ESP32SPISlave对象 #define SPI_SPLAVE_ENABLE 1 // Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 1000000, SPI_BITORDER_MSBFIRST, SPI_MODE0); #define MY_CS 12 #define MY_SCK 13 #define MY_MOSI 14 #define MY_MISO 11 // 自定义spi引脚 // SPIClass my_spi(HSPI); // 创建SPIClass对象my_spi #define SPI_READ_TIMEROUT 999999 // 10 // 50ms static constexpr size_t SPI_BUFFER_SIZE = 16 * 2; // 上位机 测试42 字节数据正常,模式1,定义SPI通信缓冲区大小为32字节 static constexpr size_t QUEUE_SIZE = 1; static uint8_t spi_tx_buf[SPI_BUFFER_SIZE]{1, 2, 3, 4, 5, 6, 7, 8};//发送缓冲区,预置测试数据1-8 static uint8_t spi_rx_buf[SPI_BUFFER_SIZE]{0, 0, 0, 0, 0, 0, 0, 0};//接收缓冲区,初始化为全0 static uint8_t spi_tx_cmd_buf[SPI_BUFFER_SIZE]{0, 0, 0, 0, 0, 0, 0, 0};//命令发送缓冲区,初始化为全0 #define SPI_TX_CACHE_BUF_LEN 1024//发送缓存总大小为1024字节 #define SPI_TX_PAGE_BUF_LEN (SPI_BUFFER_SIZE - 3) // spi 回复数据的最大长度,单次SPI通信有效数据长度 #define SPI_USER_CMD_NULL 0//空指令 #define SPI_USER_CMD_READ 1//读数据 #define SPI_USER_CMD_WRITE 2//写数据 static volatile uint8_t spi_tx_cache_buf[SPI_TX_CACHE_BUF_LEN]{0, 0, 0, 0, 0, 0, 0, 0}; static volatile int spi_tx_cache_buf_cnt = 0; // spi 发送缓存区数据长度 // static int spi_tx_page_cnt=0;//spi 发送缓存区数据长度 static volatile int spi_current_cmd = 0, spi_current_cmd_len = 0; static uint8_t spi_send_busy = 0;//发送忙标志位 static uint8_t spi_send_mode = 1; // 发送模式选择发串口 int spi_slave_data_cache_add(uint8_t *data, uint16_t len) { if (len > SPI_TX_CACHE_BUF_LEN) { /* code */ len = SPI_TX_CACHE_BUF_LEN; } for (int i = 0; i < len; i++) { /* code */ spi_tx_cache_buf[i] = data[i]; } spi_tx_cache_buf_cnt = len; return 0; } void IRAM_ATTR my_post_setup_cb(spi_slave_transaction_t *trans)//强制将函数编译到内部RAM,确保中断快速响应 { static uint8_t test_send = 0x11;//静态测试变量 int over_len = spi_tx_cache_buf_cnt - spi_current_cmd_len * SPI_TX_PAGE_BUF_LEN; // 剩余待发送数据量 = 总缓存量 - 已发送页数×单页容量 // Serial.printf("spi slave read over_len = %d cache= %d\r\n", over_len,spi_tx_cache_buf_cnt); if (over_len < 0)//数据已全部发送完成时的保护判断 { return; } if (over_len > SPI_TX_PAGE_BUF_LEN)//单包数据超限时截断处理 { over_len = SPI_TX_PAGE_BUF_LEN; } memset((void *)spi_tx_buf, 0, SPI_BUFFER_SIZE);//清空发送缓冲区(32字节全置0) spi_tx_buf[0] = 0xab; spi_tx_buf[1] = over_len; // 实际长度 spi_tx_buf[2] = spi_current_cmd_len; // 包号 for (int i = 0; i < over_len; i++)//将缓存数据拷贝到发送缓冲区(偏移3字节协议头) { /* code */ spi_tx_buf[3 + i] = spi_tx_cache_buf[spi_current_cmd_len * SPI_TX_PAGE_BUF_LEN + i]; } spi_current_cmd_len++;//包序号自增 if (spi_current_cmd_len >= 3)//包序号归零 { /* code */ spi_current_cmd_len = 0; } // Serial.printf("spi slave read cmd_len = %d ,%02x %02x %02x\n", over_len,spi_tx_buf[1], spi_tx_buf[2], spi_tx_buf[3]); } /*** * spi slave 任务 * 模式设置4 字节 * spi cmd: 0xaa 0x01 ,切换模式1,发串口1数据 * * 数据读取 64字节,发aa 01 0xff ...... * spi ack: 0xaa 0x01 ,剩余字节全部回复串口数据 */ static void spi_slave_task(void *pvParameters)//FreeRTOS任务函数标准定义 { size_t received_bytes; // 记录接收到的数据字节数 while (1)//无限循环,保持任务持续运行 { /* code */ // initializeBuffers(tx_buf, rx_buf, BUFFER_SIZE); int cs = digitalRead(MY_CS);//读取片选信号(CS)引脚状态,检测主设备是否选中本从设备 #if SPI_SPLAVE_ENABLE//条件编译开关,控制SPI从设备功能是否启用 if (cs == 0)//当片选信号为低电平时(表示被主设备选中)执行通信 { memset(spi_rx_buf, 0, SPI_BUFFER_SIZE);//清空接受缓存区 // start and wait to complete one BIG transaction (same data will be received from slave) received_bytes = slave.transfer(spi_tx_buf, spi_rx_buf, SPI_BUFFER_SIZE, SPI_READ_TIMEROUT); //tx_buf:发送缓冲区,rx_buf:接收缓冲区,BUFFER_SIZE:传输长度,READ_TIMEROUT:超时时间 // verify and dump difference with received data if (received_bytes > 0)//成功接收到数据时处理数据 { printf_log_hex("slave", spi_rx_buf, received_bytes); printf_log_hex("slave", spi_tx_buf, received_bytes); if (spi_rx_buf[1] == 0xaa && spi_rx_buf[2] == 0x01) // 当收到0xAA01时设置为读取模式,读取数据cmd { spi_current_cmd = SPI_USER_CMD_READ; // spi_current_cmd_len = spi_rx_buf[3]; } my_post_setup_cb(NULL);//调用之前分析的发送回调函数 } } #endif vTaskDelay(5 / portTICK_PERIOD_MS);//任务延时5ms } } /** * spi slave 初始化 * SPI_MODE1 * sck 13 * miso 14 * mosi 11 * ss 12 * */ void spi_slave_server_init(void) { #if SPI_SPLAVE_ENABLE slave.setDataMode(SPI_MODE3); // default: SPI_MODE1 slave.setQueueSize(QUEUE_SIZE); // default: 1 slave.begin(HSPI, 13, 11, 14, 12); // default: HSPI (please refer README for pin assignments) // pinMode(10, INPUT); // slave.setPostSetupCb(my_post_setup_cb); xTaskCreate(spi_slave_task, "spi_slave_task", 8 * 1024, NULL, 2, NULL); #endif } 仿照上述格式,写spi主机代码
09-25
#include <SPI.h> #include <Adafruit_SPIDevice.h> #include "helper.h" // 假设有 printf_log_hex 等辅助函数 #include "spi_server.h" #include <ESP32SPISlave.h> // 定义引脚 #define MY_CS 12 #define MY_SCK 13 #define MY_MOSI 14 #define MY_MISO 11 // 协议相关定义(与从机保持一致) static constexpr size_t SPI_BUFFER_SIZE = 16 * 2; // 32字节缓冲区 #define SPI_USER_CMD_READ 1 #define SPI_USER_CMD_WRITE 2 #define SPI_TX_PAGE_BUF_LEN (SPI_BUFFER_SIZE - 3) // 每包有效数据长度 // 创建 SPIDevice 对象 Adafruit_SPIDevice spi_dev(MY_CS, MY_SCK, MY_MISO, MY_MOSI, 1000000, SPI_BITORDER_MSBFIRST, SPI_MODE3); // 缓冲区 static uint8_t spi_tx_buf[SPI_BUFFER_SIZE]; static uint8_t spi_rx_buf[SPI_BUFFER_SIZE]; // 发送缓存模拟(用于测试发送多包数据) #define SPI_TX_CACHE_BUF_LEN 1024 static uint8_t spi_tx_cache_buf[SPI_TX_CACHE_BUF_LEN]; static int spi_tx_cache_buf_cnt = 0; // 全局变量 static int spi_current_cmd_len = 0; static bool spi_send_busy = false; /** * @brief 向 SPI 从机发送读取命令并接收响应 */ void spi_master_read_data() { memset(spi_tx_buf, 0, SPI_BUFFER_SIZE); memset(spi_rx_buf, 0, SPI_BUFFER_SIZE); // 构造命令帧 spi_tx_buf[0] = 0xaa; spi_tx_buf[1] = 0x01; // 请求读数据 // 使用 writeThenRead 实现全双工等效操作 if (!spi_dev.writeThenRead(spi_tx_buf, // 发送命令 spi_rx_buf, // 接收响应 SPI_BUFFER_SIZE, // 发送长度 SPI_BUFFER_SIZE, // 接收长度 false)) { Serial.println("SPI transfer failed"); return; } printf_log_hex("Master Received", spi_rx_buf, SPI_BUFFER_SIZE); // 解析响应 if (spi_rx_buf[0] == 0xab) { int data_len = spi_rx_buf[1]; int packet_id = spi_rx_buf[2]; Serial.printf("Packet %d, Data Length: %d\n", packet_id, data_len); printf_log_hex("Payload", &spi_rx_buf[3], data_len); } } /** * @brief 向 SPI 从机写入数据(模拟) */ void spi_master_read_data() { memset(spi_tx_buf, 0, SPI_BUFFER_SIZE); memset(spi_rx_buf, 0, SPI_BUFFER_SIZE); // 构造命令帧 spi_tx_buf[0] = 0xaa; spi_tx_buf[1] = 0x01; // 请求读数据 // 使用 writeThenRead 实现全双工等效操作 if (!spi_dev.writeThenRead(spi_tx_buf, // 发送命令 spi_rx_buf, // 接收响应 SPI_BUFFER_SIZE, // 发送长度 SPI_BUFFER_SIZE, // 接收长度 false)) { Serial.println("SPI transfer failed"); return; } printf_log_hex("Master Received", spi_rx_buf, SPI_BUFFER_SIZE); // 解析响应 if (spi_rx_buf[0] == 0xab) { int data_len = spi_rx_buf[1]; int packet_id = spi_rx_buf[2]; Serial.printf("Packet %d, Data Length: %d\n", packet_id, data_len); printf_log_hex("Payload", &spi_rx_buf[3], data_len); } } /** * @brief 主循环任务(运行在 FreeRTOS 任务中) */ static void spi_master_task(void *pvParameters) { // 等待 SPI 设备初始化完成 while (!spi_dev.begin()) { Serial.println("SPI begin failed, retrying..."); vTaskDelay(500 / portTICK_PERIOD_MS); } Serial.println("SPI Master initialized."); // 准备测试数据 for (int i = 0; i < SPI_TX_CACHE_BUF_LEN; i++) { spi_tx_cache_buf[i] = i % 256; } spi_tx_cache_buf_cnt = 64; // 设置要发送的数据长度 while (1) { // 示例1: 发起一次读操作 Serial.println("Sending READ command..."); spi_master_read_data(); // 示例2: 发起一次写操作 uint8_t test_data[] = {0xDE, 0xAD, 0xBE, 0xEF}; spi_master_write_data(test_data, 4); vTaskDelay(1000 / portTICK_PERIOD_MS); // 每秒执行一次 } } /** * @brief SPI 主机初始化函数 */ void spi_slave_server_init(void) { // 创建主机任务 xTaskCreate(spi_master_task, "spi_master_task", 8192, NULL, 2, NULL); } 类 "Adafruit_SPIDevice" 没有成员 "writeThenRead" 未定义标识符 "spi_master_write_data"
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值