1.为什么需要监视单片机?
在此之前尝试用过plc,发现plc的有一个在线监视模式,可以看到各个输入输出的状态以及一些寄存器,我觉得这个是很实用的!那单片机为什么不能有一个这样的东西呢?我用的是stm32的片子,相对于51来说stm32还有个单步调试可以用,可是如果有一个屏幕能够实时显示各个端口状态和变量值那不是对单片机的运行情况一目了然了么
2.数据传送方式:
我用的是串口传输,其实如果做成usb应该会更方便一点。我监视的点并不多,输入16个,输出16个,这样我用了两个16位变量就行了。
uint16_t XStatus;
uint16_t YStatus;
针对输入的话我们可以直接读,输出呢?如果需要输出的话就对YStatus进行位赋值,然后在一个定时器1ms中断中根据YStstus的值对Y进行输出。
(输入也可以在1ms变量中进行判断赋值,方然10ms,20ms都可以,取决于你的要求)
变量的话有点麻烦了,如果不需要上位机显示变量名,只需要定义一个数组就行了,但那样不直观,我是不接受。还有就是这个东西也要方便别人使用,那么别人不能添加一个变量后还要在发送函数中添加相应的发送代码,这样也很麻烦,那么,结构体就派上用场了!
结构体的优点:能够将变量名字和变量值放在相邻地址,这样便于发送,这点一会儿就会看到
typedef struct
{
char* name;
uint16_t value;
}AllVariable_Des;
struct Variable
{
AllVariable_Des _zhi;
AllVariable_Des _gao;
AllVariable_Des _chi;
AllVariable_Des _don;
AllVariable_Des _zha;
AllVariable_Des _gae;
AllVariable_Des _chz;
AllVariable_Des _dol;
};
这两个声明放在头文件中,然后在c文件中进行定义,那么如何使用呢?
1在头文件Variable中添加自己需要用的变量名字(由于我的协议是自己定义的,所以我要求自己定义的变量是四个字符)
2在c文件中对值进行初始化,改赋值的赋值,记着把.name赋值为你的变量名
3然后你该怎么写程序怎么写程序就行了,只是对Y赋值变为了对YStatus进行Bit赋值(写个函数其实是很容易变成自己习惯的赋值方式了)
3发送给上位机:
void SendMonitor(void)
{
uint16_t VarCount,i,j,k,m=0;
AllVariable_Des temp;
uint32_t Addr_var;
char data[20];
VarCount=sizeof(AllVariable_Value)/8;
Addr_var = (uint32_t)& AllVariable_Value;
for(i=0;i<VarCount;i++)
{
temp=(*(volatile AllVariable_Des *)(Addr_var+i*8));
k=strlen(temp.name);
data[0]=0x21;
data[1]=0x01;
data[2]=temp.name[0];
data[3]=temp.name[1];
data[4]=temp.name[2];
data[5]=temp.name[3];
data[6]=bcd_ascll[temp.value>>12];
data[7]=bcd_ascll[(temp.value>>8) & 0X0F];
data[8]=bcd_ascll[(temp.value & 0X00F0) >>4];
data[9]=bcd_ascll[temp.value & 0X000F];
data[10]=bcd_ascll[i];
printf("%s",data);
memset(data,0,sizeof(data));
}
YStatus=0;
for(i=1;i<17;i++)
{
YStatus=YStatus | (ystatus[m]<<(m-1));
}
data[0]=0x21;
data[1]=0x02;
data[2]=bcd_ascll[YStatus>>12];
data[3]=bcd_ascll[(YStatus>>8) & 0X0F];
data[4]=bcd_ascll[(YStatus & 0X00F0) >>4];
data[5]=bcd_ascll[YStatus & 0X000F];
data[6]=bcd_ascll[XStatus>>12];
data[7]=bcd_ascll[(XStatus>>8) & 0X0F];
data[8]=bcd_ascll[(XStatus & 0X00F0) >>4];
data[9]=bcd_ascll[XStatus & 0X000F];
data[10]=0xff;
printf("%s",data);
memset(data,0,sizeof(data));
}
代码就是上面的了,协议很简单,就一个0x21做帧头,固定11个字节,没有加什么校验。对变量值进行采集的时候是直接对地址操作的,我们首先判断出总的占用内存然后根据成员求出总共定义了多少个变量,接着利用地址累加的方式进行采集然后发送。
4END
总的思想就是这样了,希望对大家能有所帮助,如果有更好的方法,欢迎指点!