当前位置:   article > 正文

使用STM32串口模块配合SerialChart实现虚拟示波器功能_stm32虚拟示波器,通过串口,无需屏幕

stm32虚拟示波器,通过串口,无需屏幕

1、硬件连接

单片机IO口配置

2、上位机系统环境

要用Windows系统,(XP 32bit亦可)。下载好SerialChart-0.3.4。

我使用的是Keil MDK 4 + STM32CubeMX。

SerialChart配置文件:

  1. [_setup_]
  2. port=COM9
  3. baudrate=115200
  4. width=1000
  5. height=400
  6. background_color = white
  7. grid_h_origin = 0
  8. grid_h_step = 10
  9. grid_h_color = #EEE
  10. grid_h_origin_color = #000
  11. grid_v_origin = 0
  12. grid_v_step = 10
  13. grid_v_color = #EEE
  14. grid_v_origin_color = #000
  15. [_default_]
  16. min=-8
  17. max=8
  18. [interval]
  19. color=transparent
  20. min=0
  21. max=100000
  22. [InVolt]
  23. color=blue
  24. [InCurr]
  25. color=red
  26. [InPwr]
  27. [OutVolt]
  28. color=black
  29. [OutCurr]
  30. color=orange
  31. [OutPwr]
  32. [an3]
  33. color=transparent
  34. min=0
  35. max=1023

[_setup_]里:port口请选择正确的COM口,打开设备管理器确认,或者打开串口调试助手(我使用的是ATK-XCOM V2.0),即可查看对应的COM口。波特率baudrate=115200,这个参数要和STM32的对应。

[_default_]是默认参数的大小。这个范围外的界面无法显示。

[interval]以及以下的就是数据的配置,数据的名称可自由配置。[interval]是第一列数据。[InVolt]是第二列数据。[InCurr]是第三列数据。以此类推。因为当时我用这个配置文件,显示输入电流、输入电压、输出电流、输出电压,所以用这个英文名字。可以随意改的,与数据显示无关系的。

我使用的数据是:第一列是时间戳,第二列开始是CH1,第三列是CH2。

例子:SerialChart会显示一包数据:20180110083138,1.2931,0.0758

其中第一个数据是时间戳,指当前时刻是2018年1月10日8:31:38。第二个数据是CH1=1.2931V,第三个数据是CH2=0.0758V。

另外要注意在配置ADC_DMA时候,DMA要配置成Circular才可以调用HAL_ADC_Start_DMA()。如果还是DMA Mode Normal,会进入硬件hardfault_handler。不知道为什么。

3、STM32程序

参数声明:

  1. float b_PirRaw,b_PirFltr;
  2. char s_PirRaw[10];
  3. char s_PirFltr[10];
  4. uint32_t b_date, b_month, b_year, b_hour, b_minute, b_second, b_day;
  5. char s_time[25];
  6. char a_date[2], a_month[2], a_year[4], a_hour[2], a_minute[2], a_second[2];

3.1 main主函数:

  1. int main(void)
  2. {
  3. while (1)
  4. {
  5. /* USER CODE END WHILE */
  6. /* USER CODE BEGIN 3 */
  7. if(flag_100ms==1)
  8. {
  9. flag_100ms=0;
  10. SerialDisplay(); //数据通过串口发送出去
  11. }
  12. if(flag_1s==1)
  13. {
  14. flag_1s=0;
  15. UpdateDateTime(); //更新时间
  16. }
  17. }
  18. /* USER CODE END 3 */
  19. }

3.2 SerialDisplay():

  1. void SerialDisplay(void)
  2. {
  3. s_time[0] = a_year[0];
  4. s_time[1] = a_year[1];
  5. s_time[2] = a_year[2];
  6. s_time[3] = a_year[3];
  7. s_time[4] = a_month[0];
  8. s_time[5] = a_month[1];
  9. s_time[6] = a_date[0];
  10. s_time[7] = a_date[1];
  11. s_time[8] = a_hour[0];
  12. s_time[9] = a_hour[1];
  13. s_time[10] = a_minute[0];
  14. s_time[11] = a_minute[1];
  15. s_time[12] = a_second[0];
  16. s_time[13] = a_second[1];
  17. s_time[14] = '\0';
  18. float2str(b_PirRaw, 2, s_PirRaw); //将float转换为str
  19. float2str(b_PirFltr, 2, s_PirFltr); //将float转换为str
  20. strcpy(a_UartTxBuf, s_time); //将s_time复制至a_UartTxBuf
  21. strcat(a_UartTxBuf, ","); //这句语句效果是a_UartTxBuf += ","
  22. strcat(a_UartTxBuf, s_PirRaw); //这句语句效果是a_UartTxBuf += s_PirRaw
  23. strcat(a_UartTxBuf, ",");
  24. strcat(a_UartTxBuf, s_PirFltr);
  25. strcat(a_UartTxBuf, "\r\n"); //一个数据包的结尾是"\r\n",同时strlen计算字符串长度是计算到\r\n
  26. HAL_UART_Transmit(&huart1, (uint8_t*)a_UartTxBuf, strlen(a_UartTxBuf), 100); //发送数据
  27. }

以上转换时间那几行真的不怎么优雅……

3.3 float2str

浮点数转换字符串。这代码我是复制的,来自https://www.cnblogs.com/gleam/p/3607984.html

  1. /**
  2. * @brief convert float to string
  3. * @param
  4. * @usage char buf[128];
  5. * printf("%s\n", float2str((float)1234.56789, -2, buf));
  6. * @retval None
  7. */
  8. char * float2str(float val, int precision, char *buf)
  9. {
  10. char *cur, *end;
  11. sprintf(buf, "%.4f", val);
  12. if (precision < 4) {
  13. cur = buf + strlen(buf) - 1;
  14. end = cur - 4 + precision;
  15. while ((cur > end) && (*cur == '0')) {
  16. *cur = '\0';
  17. cur--;
  18. }
  19. }
  20. return buf;
  21. }

3.4 UpdateDateTime

每秒要执行一次这代码,更新本机时间。

  1. /*
  2. * @brief UpdateDateTime
  3. * input param: none
  4. * output param: none
  5. * relevent param: b_date b_month b_year b_hour b_minute b_second
  6. * must be execute every 1 second
  7. */
  8. void UpdateDateTime(void)
  9. {
  10. b_second++;
  11. if(b_second>=60)
  12. {
  13. b_second = 0;
  14. b_minute++;
  15. if(b_minute>=60)
  16. {
  17. b_minute = 0;
  18. b_hour++;
  19. if(b_hour>=24)
  20. {
  21. b_hour = 0;
  22. b_date++;
  23. if((b_date>=29)&&(b_month==2))
  24. {
  25. b_date = 1;
  26. b_month++;
  27. }
  28. if((b_date>=30)&&(b_month==2)&&(b_year%4==0))
  29. {
  30. b_date = 1;
  31. b_month++;
  32. }
  33. else if((b_date>=29)&&(b_month==2)&&(b_year%4!=0))
  34. {
  35. b_date = 1;
  36. b_month++;
  37. }
  38. else if((b_date>=31)&&((b_month==4)||(b_month==6)||(b_month==9)||(b_month==11)))
  39. {
  40. b_date = 1;
  41. b_month++;
  42. }
  43. else if((b_date>=32)&&((b_month==1)||(b_month==3)||(b_month==5)||(b_month==7)||(b_month==8)||(b_month==10)||(b_month==12)))
  44. {
  45. b_date = 1;
  46. b_month++;
  47. if(b_month>=13)
  48. {
  49. b_month = 1;
  50. b_year++;
  51. }
  52. }
  53. }
  54. }
  55. }
  56. a_year[0] = b_year/1000 + '0';
  57. a_year[1] = b_year%1000/100 + '0';
  58. a_year[2] = b_year%100/10 + '0';
  59. a_year[3] = b_year%10 + '0';
  60. a_month[0] = (uint8_t)b_month/10 + '0';
  61. a_month[1] = (uint8_t)b_month%10 + '0';
  62. a_date[0] = (uint8_t)b_date/10 + '0';
  63. a_date[1] = (uint8_t)b_date%10 + '0';
  64. a_hour[0] = (uint8_t)b_hour/10 + '0';
  65. a_hour[1] = (uint8_t)b_hour%10 + '0';
  66. a_minute[0] = (uint8_t)b_minute/10 + '0';
  67. a_minute[1] = (uint8_t)b_minute%10 + '0';
  68. a_second[0] = (uint8_t)b_second/10 + '0';
  69. a_second[1] = (uint8_t)b_second%10 + '0';
  70. }

4、显示效果

以上看到本程序使用的数据包格式是:

<Timestramp>,<ch1>,<ch2>\r\n

即实现了带时间戳的双通道数据显示。

如果需要显示4通道,可以按照这样的格式:

<Timestramp>,<ch1>,<ch2>,<ch3>,<ch4>\r\n

如果需要显示更多的数据,可以按照这样的格式:

<Timestramp>,<ch1>,<ch2>,<ch3>,<ch4>,<ch5>,<ch6>,...,<chn>\r\n

也可以不发送第一列时间戳,但要在配置文件中删除[interval]

 

 

共享了工程:

链接: https://pan.baidu.com/s/1CQk6l4ziFMHXGxQEBbF_OA 提取码: aey4

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/441182
推荐阅读
相关标签
  

闽ICP备14008679号