单片机IO口配置
要用Windows系统,(XP 32bit亦可)。下载好SerialChart-0.3.4。
我使用的是Keil MDK 4 + STM32CubeMX。
SerialChart配置文件:
[_setup_]
port=COM9
baudrate=115200
width=1000
height=400
background_color = white
grid_h_origin = 0
grid_h_step = 10
grid_h_color = #EEE
grid_h_origin_color = #000
grid_v_origin = 0
grid_v_step = 10
grid_v_color = #EEE
grid_v_origin_color = #000
[_default_]
min=-8
max=8
[interval]
color=transparent
min=0
max=100000
[InVolt]
color=blue
[InCurr]
color=red
[InPwr]
[OutVolt]
color=black
[OutCurr]
color=orange
[OutPwr]
[an3]
color=transparent
min=0
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。不知道为什么。
参数声明:
float b_PirRaw,b_PirFltr;
char s_PirRaw[10];
char s_PirFltr[10];
uint32_t b_date, b_month, b_year, b_hour, b_minute, b_second, b_day;
char s_time[25];
char a_date[2], a_month[2], a_year[4], a_hour[2], a_minute[2], a_second[2];
int main(void)
{
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(flag_100ms==1)
{
flag_100ms=0;
SerialDisplay(); //数据通过串口发送出去
}
if(flag_1s==1)
{
flag_1s=0;
UpdateDateTime(); //更新时间
}
}
/* USER CODE END 3 */
}
void SerialDisplay(void)
{
s_time[0] = a_year[0];
s_time[1] = a_year[1];
s_time[2] = a_year[2];
s_time[3] = a_year[3];
s_time[4] = a_month[0];
s_time[5] = a_month[1];
s_time[6] = a_date[0];
s_time[7] = a_date[1];
s_time[8] = a_hour[0];
s_time[9] = a_hour[1];
s_time[10] = a_minute[0];
s_time[11] = a_minute[1];
s_time[12] = a_second[0];
s_time[13] = a_second[1];
s_time[14] = '\0';
float2str(b_PirRaw, 2, s_PirRaw); //将float转换为str
float2str(b_PirFltr, 2, s_PirFltr); //将float转换为str
strcpy(a_UartTxBuf, s_time); //将s_time复制至a_UartTxBuf
strcat(a_UartTxBuf, ","); //这句语句效果是a_UartTxBuf += ","
strcat(a_UartTxBuf, s_PirRaw); //这句语句效果是a_UartTxBuf += s_PirRaw
strcat(a_UartTxBuf, ",");
strcat(a_UartTxBuf, s_PirFltr);
strcat(a_UartTxBuf, "\r\n"); //一个数据包的结尾是"\r\n",同时strlen计算字符串长度是计算到\r\n
HAL_UART_Transmit(&huart1, (uint8_t*)a_UartTxBuf, strlen(a_UartTxBuf), 100); //发送数据
}
以上转换时间那几行真的不怎么优雅……
浮点数转换字符串。这代码我是复制的,来自https://www.cnblogs.com/gleam/p/3607984.html
/**
* @brief convert float to string
* @param
* @usage char buf[128];
* printf("%s\n", float2str((float)1234.56789, -2, buf));
* @retval None
*/
char * float2str(float val, int precision, char *buf)
{
char *cur, *end;
sprintf(buf, "%.4f", val);
if (precision < 4) {
cur = buf + strlen(buf) - 1;
end = cur - 4 + precision;
while ((cur > end) && (*cur == '0')) {
*cur = '\0';
cur--;
}
}
return buf;
}
每秒要执行一次这代码,更新本机时间。
/*
* @brief UpdateDateTime
* input param: none
* output param: none
* relevent param: b_date b_month b_year b_hour b_minute b_second
* must be execute every 1 second
*/
void UpdateDateTime(void)
{
b_second++;
if(b_second>=60)
{
b_second = 0;
b_minute++;
if(b_minute>=60)
{
b_minute = 0;
b_hour++;
if(b_hour>=24)
{
b_hour = 0;
b_date++;
if((b_date>=29)&&(b_month==2))
{
b_date = 1;
b_month++;
}
if((b_date>=30)&&(b_month==2)&&(b_year%4==0))
{
b_date = 1;
b_month++;
}
else if((b_date>=29)&&(b_month==2)&&(b_year%4!=0))
{
b_date = 1;
b_month++;
}
else if((b_date>=31)&&((b_month==4)||(b_month==6)||(b_month==9)||(b_month==11)))
{
b_date = 1;
b_month++;
}
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)))
{
b_date = 1;
b_month++;
if(b_month>=13)
{
b_month = 1;
b_year++;
}
}
}
}
}
a_year[0] = b_year/1000 + '0';
a_year[1] = b_year%1000/100 + '0';
a_year[2] = b_year%100/10 + '0';
a_year[3] = b_year%10 + '0';
a_month[0] = (uint8_t)b_month/10 + '0';
a_month[1] = (uint8_t)b_month%10 + '0';
a_date[0] = (uint8_t)b_date/10 + '0';
a_date[1] = (uint8_t)b_date%10 + '0';
a_hour[0] = (uint8_t)b_hour/10 + '0';
a_hour[1] = (uint8_t)b_hour%10 + '0';
a_minute[0] = (uint8_t)b_minute/10 + '0';
a_minute[1] = (uint8_t)b_minute%10 + '0';
a_second[0] = (uint8_t)b_second/10 + '0';
a_second[1] = (uint8_t)b_second%10 + '0';
}
以上看到本程序使用的数据包格式是:
即实现了带时间戳的双通道数据显示。
如果需要显示4通道,可以按照这样的格式:
如果需要显示更多的数据,可以按照这样的格式:
也可以不发送第一列时间戳,但要在配置文件中删除[interval]
共享了工程:
链接: https://pan.baidu.com/s/1CQk6l4ziFMHXGxQEBbF_OA 提取码: aey4