1.实验工具
- STM32f103RCT6板子
- 问答式温湿度传感器(TTL信号)
- 外接SD卡模块(淘宝都差不多)
2.接线说明
1.SD卡模块,采用SPI1接线
(CLK)SCK <—>PA5
(DATA0)MISO <—>PA6
(CMD)MOSI <—>PA7
(DATA3)CS <—>PA4
前面小括号里的是SDIO模式的接线,可以忽略。
2.传感器模块
问答式TTL信号的传感器都可以,
连接到板子的串口2,PA2,PA3
3.部分代码说明
代码是在野火的SD卡测试代码上更新修改的,所以接口初始化啥的直接参考野火或者其它的就可以,主要写一下问询方式串口中断采集变量数据在主函数写入SD卡的实现。
1.文件的覆盖问题
刚开始移植野火代码是,每次写入的数据总是会把上一次的内容覆盖,所以这里需要注意两个问题:
1.文件系统的文件打开方式
res_sd = f_open(&fnew, "0:test.csv",FA_OPEN_ALWAYS | FA_WRITE );
f_open函数有三个参数,文件对象,文件名,文件打开方式,文件打开方式如下图:
这里英文解释很容易明白,我们选择FA_OPEN_ALWAYS模式,如果文件存在直接打开,不存在就创建。
2.移动文件初始写入指针位置
//文件对象的读写指针移动到文件结束处
f_lseek (&fnew,f_size (&fnew));
printf("%lu",f_size (&fnew));
f_lseek函数移动指针,此函数用于文件指针的移动,共有两个参数,第一个参数为文件对象,第二个参数为移动的字节数。 f_size函数获取文件字节大小。
完成这两个才可以保证下一次的写入数据是接着之前写入。
2.变量的转换及写入问题
1.因为SD卡只能写入字符串类型,所以采集的变量数据必须先转换为字符串,然后再进行写入操作即可,要将变量数据转换为字符串,就用到了sprintf函数。
1.sprintf函数
Sprintf函数具体形式: int sprintf( char *buffer, const char *format, [ argument,…] );
解释:整形输出 sprintf(输出数组地址,<格式字符串>,参量表……)
注:只要在printf中可以使用的格式化字符串,在sprintf都可以使用。
如:
sprintf(buff,"%.1f%RH,%.1f℃\n",humidity,temperature);
buff为已经定义的char类型的一个字符串接收数组,将后面数即温湿度浮点型存入buff数组,注意换行符前不要有空格,否则可能无效。
2.CSV文件创建
//创建CSV文件
res_sd = f_open(&fnew, "0:test.csv",FA_OPEN_ALWAYS | FA_WRITE );
res_sd= f_write(&fnew,buff,sizeof(buff),&fnum);
在打开文件那一步创建的,与txt文件一样,只是后缀不同,写入数据时,逗号即代表下一列写入,逗号对应sprintf转换里第二个参数里几个逗号。
sprintf(buff,"%.1f%RH,%.1f℃\n",humidity,temperature);
3.数据采集流程(主函数、中断函数处理代码)
读取问答式温湿度传感器数据,当主程序向串口2的传感器发送问询指令后,传感器产生应答,发送当前的温湿度数据,进入中断,当返回的数据记录解析完成后,将主函数中调用中断采集的温湿度变量转成字符串类型,执行写入SD卡操作,主函数没发送一次采集指令,就在中断了写入记录一次,所以指令发送延时长一点比较好。
main函数:
FATFS fs; /* FatFs文件系统对象 */
FIL fnew; /* 文件对象 */
FRESULT res_sd; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
extern SD_CardInfo SDCardInfo;
extern float temperature;//使用中断里的温度变量
extern float humidity;//使用中断里的湿度变量
int main(void)
{
u8 buf[8]={0x01,0x03,00,0x02,00,0x02,0x65,0xCB};
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
/* 初始化系统定时器 */
SysTick_Init();
/* 初始化调试串口,一般为串口1 */
USART_Config();
uart2_init(9600); //串口2初始化为9600 ,按照用到的传感器进行匹配设置
/*初始化DTT11的引脚*/
while(1)
{
char buff[20];//接收变量转换的字符串
uart2_send_buff(buf,8);//发送问询命令
sprintf(buff,"%.1f%RH,%.1f℃\n",humidity,temperature);
//在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化
res_sd = f_mount(&fs,"0:",1);
/*----------------------- 格式化测试 ---------------------------*/
/* 如果没有文件系统就格式化创建创建文件系统 */
if(res_sd == FR_NO_FILESYSTEM)
{
printf("》SD卡还没有文件系统,即将进行格式化...\r\n");
/* 格式化 */
res_sd=f_mkfs("0:",0,0);
if(res_sd == FR_OK)
{
printf("》SD卡已成功格式化文件系统。\r\n");
/* 格式化后,先取消挂载 */
res_sd = f_mount(NULL,"0:",1);
/* 重新挂载 */
res_sd = f_mount(&fs,"0:",1);
}
else
{
printf("《《格式化失败。》》\r\n");
while(1);
}
}
else if(res_sd!=FR_OK)
{
printf("!!SD卡挂载文件系统失败。(%d)\r\n",res_sd);
printf("!!可能原因:SD卡初始化不成功。\r\n");
while(1);
}
else
{
printf("》文件系统挂载成功,可以进行读写测试\r\n");
}
/*----------------------- 文件系统测试:写测试 -----------------------------*/
/* 打开文件,如果文件不存在则创建它 */
printf("\r\n****** 即将进行文件写入测试... ******\r\n");
//注意f_open第三个参数,打开文件模式设置要注意
//创建CSV文件
res_sd = f_open(&fnew, "0:test.csv",FA_OPEN_ALWAYS | FA_WRITE );
if ( res_sd == FR_OK )
{
printf("》打开/创建test.csv文件成功,向文件写入数据。\r\n");
//文件对象的读写指针移动到文件结束处
f_lseek (&fnew,f_size (&fnew));
printf("%lu",f_size (&fnew));
/* 将指定存储区内容写入到文件内 */
res_sd= f_write(&fnew,buff,sizeof(buff),&fnum);
if(res_sd==FR_OK)
{
printf("》文件写入成功,写入字节数据:%d\n",fnum);
printf("%lu",f_size (&fnew));
}
else
{
printf("!!文件写入失败:(%d)\n",res_sd);
}
/* 不再读写,关闭文件 */
f_close(&fnew);
f_mount(NULL,"0:",1);
}
else
{
printf("!!打开/创建文件失败。\r\n");
}
Delay_ms(5000);
}
}
串口2中断函数处理部分:文章来源:https://www.toymoban.com/news/detail-454372.html
//功能:串口2中断服务程序,接收到数据会进入这个函数
//参数:无
//返回:无
u8 USART_RX_BUF[9];//定义接收数组,看传感器返回的有多少字节数据
u8 USART_RX_STA=0;//数组标志位,如第0位、第一位
static char start=0; //开始接收数据标志位
float temperature=0;//定义温湿度变量
float humidity=0;
FATFS fs; /* FatFs文件系统对象 */
FIL fnew; /* 文件对象 */
FRESULT res_sd; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
extern SD_CardInfo SDCardInfo;
void USART2_IRQHandler(void)
{
u8 Res=0;//定义一个数来接收每次读取的数据
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断,每一个字节都会中断一次
{
Res =USART_ReceiveData(USART2); //读取接收到的字节数据
//接收数据时不要随便加入占用时间的命令,如串口打印,会影响下面数据字节的接收
// printf("%x ",Res);
if(Res == 0x01) //如果接收的第一位数据是0XFF(这个是查看传感器的手册得知的,这里相当于进行校验)
{
//printf("第一个采集");
start=1; //开始接收数据标志位,一旦第一个接收正确,就就继续向下接收
}
if(start== 1)
{
USART_RX_BUF[USART_RX_STA] = Res ; //把接收到的数据存到数组里面
// printf("%x ",Res);
USART_RX_STA++;//数组标志位加1
if(USART_RX_STA >= 9 && (USART_RX_BUF[1]==0x03))//这里还校验了接收的第二个数据
{
// printf("采集结束");
temperature=(USART_RX_BUF[3]*256+USART_RX_BUF[4])*0.1 ;
humidity=(USART_RX_BUF[5]*256+USART_RX_BUF[6])*0.1 ;
printf("温度:%.1f 湿度:%.1f\n",temperature,humidity);//通过串口1打印接收数组里的数据
USART_RX_STA=0;//重新开始接收
USART_RX_BUF[0] = 0;
start=0;
}
}
}
}
//功能:串口2发送一个字符
//参数:temp发送的字符
//返回:无
void uart2_send_char(u8 temp)
{
USART_SendData(USART2,(u8)temp);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
}
//功能:串口1发送字符串
//参数:buf发送的字符串,len字符串的长度
//返回:无
void uart2_send_buff(u8* buf,u32 len)
{
u32 i;
for(i=0;i<len;i++)
uart2_send_char(buf[i]);
}
4.采集结果
文章来源地址https://www.toymoban.com/news/detail-454372.html
到了这里,关于STM32采集问答式串口传感器数据写入SD卡(spi模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!