OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3498|回复: 3

STM32F103通过ADC获取电压后进行压力计算,结果写入SD卡,单独运行没问题,合并后出现卡死

[复制链接]

3

主题

7

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2022-2-3
在线时间
9 小时
发表于 2022-2-3 01:32:21 | 显示全部楼层 |阅读模式
1金钱
大神们好,我是单片机才开始学习个把月的小白一名,现在要实现一个工程,利用STM32F103通过ADC进行传感器的值获取,把获取的结果进行压力值计算,计算后的压力值写入SD卡中的TXT文件里,现在碰到的问题是单独运行ADC和OLED都没有任何问题,OLED能正常显示压力值的变化;单独运行SD卡的文件系统进行文件创建和写入都没问题,我的SD是通过SPI进行连接;但两个系统合并在一起后就出现卡死问题,请教大神帮忙解决下,我是哪里漏了,是否是需要进行ADC的中断,我对C不是很熟悉,值熟悉HTML和PHP与MYSQL,现在接触C就从单片机进行接触,所以里面的赋值可能很不规范!
  1. #include "system.h"
  2. #include "SysTick.h"
  3. #include "usart.h"
  4. #include "adc.h"
  5. #include "oled.h"
  6. #include "bmp.h"
  7. #include "ff.h"
  8. #include "bsp_spi_sdcard.h"
  9. #include "stdio.h"

  10. FATFS fs;                                                                                                        /* FatFs文件系统对象 */
  11. FIL fnew;                                                                                                        /* 文件对象 */
  12. UINT fnum;
  13. FRESULT res_flash;                /* 文件操作结果 */

  14. #define PRESS_MIN        20
  15. #define PRESS_MAX        8000
  16. //压力范围设定


  17. #define VOLTAGE_MIN 100
  18. #define VOLTAGE_MAX 3300
  19. //电压范围设定

  20. u8 state = 0;
  21. u16 val = 0;
  22. u16 value_AD = 0;
  23. u8 buf[10];

  24. long PRESS_AO = 0;
  25. int VOLTAGE_AO = 0;

  26. long map(long x, long in_min, long in_max, long out_min, long out_max);                //计算PRESS_AO压力值

  27. void Writer_Press_AO(long press_ao,u8 ad_number)                        //写入SD卡
  28. {
  29.         u32 time_get_temp;
  30.         char filename[20];
  31.         char writerbuff[40];
  32.         res_flash = f_mount(&fs,"0:",1);
  33.         if(res_flash == FR_OK)
  34.         {
  35.                 printf("》初始化成功。\r\n");
  36.         }
  37.         else
  38.         {
  39.                 printf("》初始化失败。错误号:%d\r\n",res_flash);
  40.         }
  41.         time_get_temp = get_fattime();
  42.         printf("》时间戳:%d\r\n",time_get_temp);
  43.         sprintf(filename,"0:date%d.txt",time_get_temp);
  44.         printf("》文件名:%s\r\n",filename);
  45.         res_flash = f_open(&fnew,filename,FA_OPEN_ALWAYS | FA_WRITE );
  46.         if(res_flash == FR_OK)
  47.         {
  48.                 printf("》打开文件成功。\r\n");
  49.         }
  50.         else
  51.         {
  52.                 printf("》打开文件错误。错误号:%d\r\n",res_flash);
  53.         }
  54.         f_lseek(&fnew, f_size(&fnew));
  55.         sprintf(writerbuff,"time:%d ad:%d press_ao:%ld\r\n",time_get_temp,ad_number,press_ao);
  56.         printf("》记录值,时间:%d,端口%d:,压力值:%d\r\n",time_get_temp,ad_number,press_ao);
  57.         if ( res_flash == FR_OK )
  58.         {
  59.                 printf("》打开/创建文件成功,向文件写入数据。\r\n");               
  60.                 res_flash=f_write(&fnew,writerbuff,sizeof(writerbuff),&fnum);
  61.                 if(res_flash==FR_OK)
  62.                 {
  63.                         printf("》文件写入成功,写入字节数据:%d\n",fnum);
  64.                         printf("》向文件写入的数据为:\r\n%s\r\n",writerbuff);
  65.                 }
  66.                 else
  67.                 {
  68.                         printf("》!!文件写入失败:(%d)\r\n",res_flash);
  69.                 }   
  70.         }
  71.         f_close(&fnew);       
  72.         f_mount(NULL,"0:",1);
  73. }

  74. long Get_Adc_Press_Ao(u8 adc_port)                //从ADC获取4个端口的值
  75. {
  76.         value_AD = Get_Adc_Average(adc_port,10);        //10次平均值
  77.         VOLTAGE_AO = map(value_AD, 0, 4095, 0, 3300);
  78.         if(VOLTAGE_AO < VOLTAGE_MIN)
  79.         {
  80.                 PRESS_AO = 0;
  81.         }
  82.         else if(VOLTAGE_AO > VOLTAGE_MAX)
  83.         {
  84.                 PRESS_AO = PRESS_MAX;
  85.         }
  86.         else
  87.         {
  88.                 PRESS_AO = map(VOLTAGE_AO, VOLTAGE_MIN, VOLTAGE_MAX, PRESS_MIN, PRESS_MAX);
  89.         }
  90.        
  91.         return PRESS_AO;
  92. }


  93. int main()
  94. {
  95.         u8 i;
  96.         long result;
  97.         u32 time_get_temp;
  98.         char filename[20];
  99.         char writerbuff[40];
  100.         char* adc_temp;
  101.         SysTick_Init();
  102.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
  103.         USART1_Init(9600);
  104.         Adc_Init();
  105.         OLED_Init();
  106.         OLED_ColorTurn(0);//0正常显示,1 反色显示
  107.   OLED_DisplayTurn(1);//0正常显示 1 屏幕翻转显示
  108.         OLED_Refresh();
  109.         delay_ms(1000);
  110.         OLED_ShowChinese(9,14,0,16);
  111.         OLED_ShowChinese(27,14,1,16);
  112.         OLED_ShowChinese(45,14,2,16);
  113.         OLED_ShowChinese(63,14,3,16);
  114.         OLED_ShowChinese(81,14,4,16);
  115.         OLED_ShowChinese(99,14,5,16);
  116.         OLED_ShowChinese(9,36,6,16);
  117.         OLED_ShowChinese(27,36,7,16);
  118.         OLED_ShowChinese(45,36,8,16);
  119.         OLED_ShowChinese(63,36,9,16);
  120.         OLED_ShowChinese(81,36,10,16);
  121.         OLED_ShowChinese(99,36,11,16);
  122.         OLED_Refresh();
  123.         delay_ms(1000);
  124.         delay_ms(1000);
  125.         OLED_Clear();
  126.                
  127.        
  128.         while(1)
  129.         {
  130.                 for(i=0;i<4;i++)
  131.                 {
  132.                         result = Get_Adc_Press_Ao(i);                //每个端口进行获取ADC值
  133.                         sprintf(adc_temp,"AD%d:",i+1);                //打印OLED显示字符串
  134.                         OLED_ShowString(0,i*16,adc_temp,16);                //OLED显示
  135.                         OLED_ShowNum(40,i*16,result,4,16);
  136.                         OLED_ShowString(80,i*16,"g",16);
  137.                         if(result == 8000)                //就是这个if调用后就不正常了,注释后OLED正常显示获取的AD值,我想要的是当换算出来的AD值达到8000后,把这个记录写入到SD卡的TXT中
  138.                         {
  139.                                 Writer_Press_AO(result,i);                //调用获取的ADC值及端口号传入写入SD卡TXT文件
  140.                         }
  141.                         OLED_Refresh();
  142.                         delay_ms(1000);
  143.                 }
  144.                
  145.         }
  146. }

  147. long map(long x, long in_min, long in_max, long out_min, long out_max) {                //ADC获取电压进行压力值计算
  148. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  149. }

复制代码
while(1)里面的if语句只要一运行就卡死,OLED也不显示,注释后又正常,请教大神指点一二!!!!

最佳答案

查看完整内容[请看2#楼]

谢谢各位老师,应该是卡死在调用writer_press_ao调用上,虽然我解决了,解决的方法是把调用TF卡写入函数分开写入main里面,全部就运行正常了,现在不清楚为什么,语句都没修改,就是拆开main里面挂载TF卡,在while里面触发if条件后f_open文件,在f_writer,最后f_close,然后正常,但这种写在main里面是不是占用栈空间
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2022-2-3
在线时间
9 小时
 楼主| 发表于 2022-2-3 01:32:22 | 显示全部楼层
谢谢各位老师,应该是卡死在调用writer_press_ao调用上,虽然我解决了,解决的方法是把调用TF卡写入函数分开写入main里面,全部就运行正常了,现在不清楚为什么,语句都没修改,就是拆开main里面挂载TF卡,在while里面触发if条件后f_open文件,在f_writer,最后f_close,然后正常,但这种写在main里面是不是占用栈空间
回复

使用道具 举报

4

主题

911

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4500
金钱
4500
注册时间
2019-9-4
在线时间
913 小时
发表于 2022-2-8 11:22:59 | 显示全部楼层
你仿真一下,看看具体是卡死在哪个语句上
回复

使用道具 举报

11

主题

2146

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4886
金钱
4886
注册时间
2015-1-10
在线时间
611 小时
发表于 2022-2-9 14:32:58 | 显示全部楼层
你是if判断卡死了呢还是运行Writer_Press_AO卡死的呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-20 11:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表