在我们使用 STM32 或者 FPGA 采集数据的时候,需要将数据存储到SD卡中,因为数据是按照地址存储的,并且没有文件结构,所以不能直接用电脑的文件管理器读取,下面是一种读取数据的办法
0. 实验平台
正点原子STM32F407ZG探索者
1. Python生成写入的数据
# %%
# 定义生成文件的大小(字节数)
file_size = 512
# 递增数据的起始值
start_value = 1
# 打开文件并写入递增数据
with open('output.bin', 'wb') as file:
# 递增循环直到达到文件大小
for i in range(file_size):
# 将递增数据写入文件(使用小端字节序)
file.write(start_value.to_bytes(1, byteorder='little'))
# 递增起始值
start_value += 1
# 如果起始值超过255,则回绕到0
if start_value > 10:
start_value = 0
运行完此代码后,将会在当前文件夹里面生成一个output.bin
的二进制文件,我们可以使用16进制的文本阅读器打开查看里面的内容
2. STM32源码
注意:数据需要以0x66aa结尾,这里是自定义的,具体的结尾标志可以自己设定。完整代码可以查看本文章顶部的资源
2.1 接收串口中断函数
void USART_UX_IRQHandler(void)
{
uint8_t rxdata;
#if SYS_SUPPORT_OS /* 如果SYS_SUPPORT_OS为真,则需要支持OS. */
OSIntEnter();
#endif
if (USART_UX->SR & (1 << 5)) /* 接收到数据 */
{
rxdata = USART_UX->DR;
if ((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成? */
{
if (g_usart_rx_sta & 0x4000) /* 接收到了0x66? */
{
if (rxdata != 0xaa) /* 接收到了0xaa? (必须先接收到到0x66,才检查0xaa) */
{
g_usart_rx_sta &= ~0x4000;
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = 0x66; /* 存储数据到 g_usart_rx_buf */
g_usart_rx_sta++;
if (rxdata == 0x66)
{
g_usart_rx_sta |= 0x4000; /* 标记接收到了 0x66 */
}
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = rxdata; /* 存储数据到 g_usart_rx_buf */
g_usart_rx_sta++;
if (g_usart_rx_sta > (USART_REC_LEN - 1))g_usart_rx_sta = 0;/* 接收数据溢出, 重新开始接收 */
}
}
else
{
g_usart_rx_sta |= 0x8000; /* 收到了0x0a,标记接收完成了 */
}
}
else /* 还没收到0x0d */
{
if (rxdata == 0x66)
{
g_usart_rx_sta |= 0x4000; /* 标记接收到了 0x66 */
}
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = rxdata; /* 存储数据到 g_usart_rx_buf */
g_usart_rx_sta++;
if (g_usart_rx_sta > (USART_REC_LEN - 1))g_usart_rx_sta = 0;/* 接收数据溢出, 重新开始接收 */
}
}
}
}
#if SYS_SUPPORT_OS /* 如果SYS_SUPPORT_OS为真,则需要支持OS. */
OSIntExit();
#endif
}
2.2 主函数
int main(void)
{
uint8_t key;
uint16_t t = 0;
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(84, 115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
while (sd_init()) /* 检测不到SD卡 */
{
}
/* 打印SD卡相关信息 */
show_sdcard_info();
uint8_t k=0;
uint8_t i=0;
state[i] = sd_write_disk(data,0,10);
uint16_t len;
len = 0;
while (1)
{
key = key_scan(0);
if (key == KEY0_PRES) /* KEY0按下了 */
{
sd_test_read(0,1); /* 从0扇区读取1*512字节的内容 */
}
if (g_usart_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
for (t = 0; t < len; t++)
{
USART_UX->DR = g_usart_rx_buf[t];
while ((USART_UX->SR & 0X40) == 0); /* 等待发送结束 */
}
state[0] = sd_write_disk(g_usart_rx_buf,0,1);
if (state[0] == 0)
{
printf("\r\n%d\r\n",len);
printf("Write over!\r\n");
}
printf("\r\n\r\n"); /* 插入换行 */
g_usart_rx_sta = 0;
}
}
}
3. Python读取SD卡代码
使用读卡器将 SD 卡连接到电脑上,
如果弹出磁盘已损坏之类的千万不要管!!!
如果弹出磁盘已损坏之类的千万不要管!!!
如果弹出磁盘已损坏之类的千万不要管!!!
继续往下看!
import struct
disk = open(r"\\.\PhysicalDrive1","rb") # 打开磁盘0,PhysicalDrive不区分大小写
# 读取第一个扇区, 也就是磁盘主引导记录, 1扇区为512字节
data = disk.read(512)
data = struct.unpack(len(data)*'B',data)
print(data)
然后注意上方代码中的PhysicalDrive1
这里的1对应电脑的硬盘序号,可以此电脑(右键)->管理->磁盘管理中看到,这里的序号就是 PhysicalDrive
后面要跟的数字,我的电脑显示是磁盘 1
,所以写的是 1
。
4. 验证结果
运行上面的程序即可得到结果,这里是没有解包的结果
这一段代码是解包的过程,详细的可以查看这一篇博客:Python Struct 库之 pack 和 unpack 详解
取消注释下列代码后的结果
data = struct.unpack(len(data)*'B',data)