用Random_buffer产生随机序列

使用random_shuffle()算法随机化序列元素  

假设你需要指定范围内的随机数,传统的方法是使用ANSI C的函数random(),然后格式化结果以便结果是落在指定的范围内。

但是,使用这个方法至少有两个缺点。首先,做格式化时,结果常常是扭曲的,所以得不到正确的随机数(如某些数的出现频率要高于其它数) 。

其次,random()只支持整型数;不能用它来产生随机字符,浮点数,字符串或数据库中的记录。


  对于以上的两个问题,C++中提供了更好的解决方法,那就是random_shuffle()算法。不要着急,下面我就会告诉你如何用这种算法来产生不同类型的随机数。

  产生指定范围内的随机元素集的最佳方法是创建一个顺序序列(也就是向量或者内置数组),在这个顺序序列中含有指定范围的所有值。例如,如何你需要产生100个0-99之间的数,那么就创建一个向量并用100个按升序排列的数填充向量:  

#include <vector>
using std::vector;
int main()
{ 
vector<int> vi; 
for (int i = 0; i < 10; i++) 
	vi.push_back(i);
/*现在向量包含了 100 个 0-99 之间的整数并且按升序排列*/
} 
 

填充完向量之后,用random_shuffle()算法打乱元素排列顺序。random_shuffle()定义在标准的头文件<algorithm.h>中。因为

所有的STL算法都是在名字空间std中声明的,所以你要注意正确地声明数据类型。

random_shuffle()有两个参数,第一个参数是指向序列首元素的迭代器,第二个参数则指向序列最后一个元素的下一个位置。

下列代码段用random_shuffle()算法打乱了先前填充到向量中的元素:  

#include <algorithm>
using std::random_shuffle;
random_shuffle(vi.begin(), vi.end()); /* 打乱元素 */ 

random_shuffle()是个完全通用的算法-适用于内建的数据类型和用户自定义类型。

下面的例子创建了一个有7个字符串对象的向量,它包含一周的天数并使用random_shuffle()打乱他们的排列顺序:  

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
 vector<string> vs; 
vs.push_back(string ("Sunday"));
 vs.push_back (string ("Monday"));
 ... vs.push_back (string ("Saturday"));
 random_shuffle(vs.begin(), vs.end()); /* 打乱顺序 */ 
for (int i = 0; i << 7; i++) 
	cout<<vs[i]; /* 显示打乱顺序后的元素 */}

如何使用random_shuffle()处理内置数组

  在使用容器代替内置数组时,你不要有什么负担。所有STL算法不仅适用于容器,也适用于序列。因此,你也能将random_shuffle()算法应用于内置数组。只是要注意random_shuffle()的第二个参数要指向数组上界的下一个元素位置:  

char carr[4] = {''a'', ''b'', ''c'', ''d''};/*carr+4 指向数组上界的下一个元素位置*/

random_shuffle(carr, carr+4); 

for (int i = 0; i < 4; i++) 

cout<<carr[i]; /* 显示被打乱顺序的元素 */

#include "spi_slave_server.h" // SPI 库 #include <SPI.h> #include <ESP32SPISlave.h> #include "helper.h" #include <main.h> ESP32SPISlave slave; // 自定义引脚 #define MY_CS 12 #define MY_SCK 13 #define MY_MOSI 14 #define MY_MISO 11 // 启用 SPI Slave 功能 #define SPI_SLAVE_ENABLE 1 // 超时设置(微秒) #define SPI_READ_TIMEOUT 999999 #define SPI_TX_CACHE_BUF_LEN 1024 static volatile uint8_t spi_tx_cache_buf[SPI_TX_CACHE_BUF_LEN]; static volatile int spi_tx_cache_buf_cnt = 0; // 实现缺失的函数 int spi_slave_data_cache_add(uint8_t *data, uint16_t len) { if (len > SPI_TX_CACHE_BUF_LEN) len = SPI_TX_CACHE_BUF_LEN; for (int i = 0; i < len; ++i) spi_tx_cache_buf[i] = data[i]; spi_tx_cache_buf_cnt = len; return 0; } // 扩展缓冲区至 64 字节以容纳 33 字节的有效响应 static constexpr size_t SPI_BUFFER_SIZE = 64; static constexpr size_t QUEUE_SIZE = 1; // SPI 发送/接收缓冲区 static uint8_t spi_tx_buf[SPI_BUFFER_SIZE] = {0}; static uint8_t spi_rx_buf[SPI_BUFFER_SIZE] = {0}; // 用户命令定义 #define SPI_USER_CMD_NULL 0 #define SPI_USER_CMD_READ 1 #define SPI_USER_CMD_WRITE 2 // 当前命令状态 static volatile int spi_current_cmd = SPI_USER_CMD_NULL; static volatile int spi_current_cmd_len = 0; // 包序号或控制标志 // 发送忙标志(预留扩展) static uint8_t spi_send_busy = 0; static uint8_t spi_send_mode = 1; /** * 生成 16 个随机 16 位数据,并写入 buffer(32 字节) */ void generate_random_16bit_data(uint8_t *buffer, int count) { for (int i = 0; i < count; i++) { uint16_t val = random(0xFFFF); // 随机 16 位值 buffer[i * 2 + 0] = (val >> 8) & 0xFF; // 高字节 buffer[i * 2 + 1] = val & 0xFF; // 低字节 } } /** * SPI 事务完成后的回调函数(放在 IRAM 中保证中断快速响应) */ void IRAM_ATTR my_post_setup_cb(spi_slave_transaction_t *trans) { // 如果当前处于读取模式且尚未响应,则构造 0xAA + 32字节数据 if (spi_current_cmd == SPI_USER_CMD_READ && spi_current_cmd_len == 0) { memset(spi_tx_buf, 0, SPI_BUFFER_SIZE); // 清空缓冲区 spi_tx_buf[0] = 0xAA; // 回复标识 generate_random_16bit_data(spi_tx_buf + 1, 16); // 写入 16 个 16 位随机数(32字节) // 标记已响应,防止重复发送 spi_current_cmd_len = 1; } else { // 默认响应(可用于调试) memset(spi_tx_buf, 0, SPI_BUFFER_SIZE); spi_tx_buf[0] = 0xAB; spi_tx_buf[1] = spi_current_cmd_len; spi_tx_buf[2] = millis() >> 8; spi_tx_buf[3] = millis(); } } /** * SPI Slave 任务(FreeRTOS 任务) */ static void spi_slave_task(void *pvParameters) { size_t received_bytes; while (1) { int cs = digitalRead(MY_CS); #if SPI_SLAVE_ENABLE if (cs == 0) { // 片选拉低,表示主设备开始通信 memset(spi_rx_buf, 0, SPI_BUFFER_SIZE); // 执行一次 SPI 传输(阻塞直到完成或超时) received_bytes = slave.transfer(spi_tx_buf, spi_rx_buf, SPI_BUFFER_SIZE, SPI_READ_TIMEOUT); if (received_bytes > 0) { printf_log_hex("SPI RX", spi_rx_buf, received_bytes); // 检查是否收到 0xAA 命令(假设命令在第一个字节) if (spi_rx_buf[0] == 0xAA) { spi_current_cmd = SPI_USER_CMD_READ; spi_current_cmd_len = 0; // 准备下次回复 printf("SPI Slave: Received 0xAA command, will respond in next transaction.\n"); } // 调用回调函数准备下一次的响应数据 my_post_setup_cb(NULL); } } #endif vTaskDelay(5 / portTICK_PERIOD_MS); // 小延时避免 CPU 占满 } } /** * 初始化 SPI Slave */ void spi_slave_server_init(void) { #if SPI_SLAVE_ENABLE // 设置 SPI 模式(MODE3 示例) slave.setDataMode(SPI_MODE3); slave.setQueueSize(QUEUE_SIZE); // 初始化 SPI Slave(使用 HSPI,自定义引脚) slave.begin(HSPI, MY_SCK, MY_MISO, MY_MOSI, MY_CS); // 初始化随机种子(用于生成随机数) randomSeed(micros()); // 创建 SPI 从机任务 xTaskCreate(spi_slave_task, "spi_slave_task", 8192, NULL, 2, NULL); printf("SPI Slave initialized in MODE3, Buffer Size: %d\n", SPI_BUFFER_SIZE); #endif } 将发送的数据改为有规律的数
最新发布
09-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值