关于匿名上位机好久没有使用了,之前也发过一篇,里面涉及到了一点匿名上位机的使用,最近又重操旧业,再熟悉一下。
—————————————————————————————————————————————————————
Being jealous is a kind of worship —————————————————————————————————————————————————————
前言
我用的是V4.22版本,软件中有通信协议的介绍,写程序的时候就要严格按照上位机的通讯协议来写 1,我这里用的单片机是stm32f1系列,这里介绍一下数据格式及其范围,等会会用到: stm32F1系列的CPU为32位,即int位32位 无符号整型 unsigned int:0~4,294,967,295 有符号整型 int:-2,147,483,648~2,147,483,647
无符号字符型 unsigned char:0~255 有符号字符型 char:-128~127
无符号短整型 unsigned short (int):0~65535 有符号短整型 short (int):-32768~32767
无符号整型 unsigned int:0~4,294,967,295 有符号整型 int:-2,147,483,648~2,147,483,647
浮点型 float:-2,147,483,648~2,147,483,647 ————————————————————————————————————————————————————— 2,
这里用户可以使用十个自己设置的帧,帧格式如通信协议中所注明的如下图所示,每个帧里面可以有三十个数据,20个数据容器是指在画图的时候有二十条曲线与之对应,即每帧中的三十个数据中的二十个数据可以有二十条曲线用来画图. 还有数据格式要注意,如果发送的数据是u16类型的,short也是16位的都是两个字节,就要单独分高8位、低8位发送,与0xff与后放入u8的数组里面 代码如下
u8 tramsmit_buff[2];
tbuf[0]=(short_MSB>>8)&0XFF;
tbuf[1]=short_LSB&0XFF;
-------------------------------------------------------
最高位 最低位
short_MSB short_LSB
11111111 10101010
那么tbuf[0]=11111111,tbuf[1]=10101010大家可以用单片机debug一下看看是否如此
发送给匿名上位机是高位字节放在数组低位
程序
例子:在单片机上用sin函数生成一个数组,发送给匿名上位机,得到其波形。
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
void usart1_send_char(u8 c)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,c);
}
void usart1_niming_report(u8 fun,u8*data,u8 len)
{
u8 send_buf[32];
u8 i;
if(len>28)return;
send_buf[len+4]=0;
send_buf[0]=0XAA;
send_buf[1]=0XAA;
send_buf[2]=fun;
send_buf[3]=len;
for(i=0;i<len;i++)send_buf[4+i]=data[i];
for(i=0;i<len+4;i++)send_buf[len+4]+=send_buf[i];
for(i=0;i<len+5;i++)usart1_send_char(send_buf[i]);
}
int main()
{
u16 i;
short array[1];
u8 buff[2];
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
uart_init(115200);
while(1)
{
for(i=0;i<20;i++)
{
array[0]=1000*sin(0.1*3.1415926*i);
buff[0]=(array[0]>>8)&0xFF;
buff[1]=array[0]&0xFF;
usart1_niming_report(0xF1,buff,2);
}
}
}
注意: 1,usart1_niming_report函数中可以举个例子,比如len为1,用的是数据帧1,那么数据帧格式就是
FF FF F1 01 数据字节 校验和
0 1 2 3 4 5
上面关系再代入下面代码理解
send_buf[1+4]=0;
send_buf[0]=0XAA;
send_buf[1]=0XAA;
send_buf[2]=fun;
send_buf[3]=len;
for(i=0;i<len;i++)send_buf[4+i]=data[i];
2,for循环中的20是sin(0.1?3.1415926?i)的周期,这里我刚好取一个完整周期,20个数据,前面要乘以1000是因为提高精度,比如i=1时候,sin(0.13.14159261)=0.309,我用单片机debug了一下,这个值直接为0x0000;乘以1000后就是309了 16进制135就是十进制309
结果
最后在匿名上位机是查看图形
—————————————————————————————————————————————————————
补:定时器的预装载寄存器和影子寄存器
之前发现配置定时器PWM的时候有这两条语句
TIM_ARRPreloadConfig(TIM4, ENABLE)
TIM_0C2PreloadConfig(TIM4, ENABLE)
看下图 图中有阴影的小方框,代表该功能对应的寄存器有影子寄存器,也就是:PSC预分频器、自动重装载寄存器、REP寄存器和4个通道的捕获/比较寄存器。
阴影的寄存器,表示在物理上这个寄存器对应2个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装载寄存器),另一个是程序员看不见的、但在操作中真正起作用的寄存器,称为shadow register(影子寄存器);正如手册上的14.3.1节所说,根据TIMx_CR1寄存器中APRE位的设置,preload register的内容可以随时传送到shadow register,即两者是连通的(permanently),或者在每一次更新事件(UEV)时才把preload register的内容传送到shadow register。 TIM_ARRPreloadConfig(TIM4, DISABLE); 就是上图右边红色时的情况,立刻更新shadow register TIM_ARRPreloadConfig(TIM4, ENABLE); 则是蓝色的情况,通过预装载寄存器,等待下一个跟新时刻再改变shadow register
|