标准框架:

这是一个上行AD和接收下行命令的标准框架,可以通过修改来适应于其他各种系统:

参数变量定义:

u16 sec=0; //定时计数
char buf[160];    //合成字符串缓存,用于一般的字符串处理

char recv[128];//用于串口的接收缓存
u8 rjs=0;        //recv buf的计数指针,用于记录当前的接收数据存储位置
u8 iscmd;        //==1 表示出于cmd记录中,状态 内部使用
u8 iscmdok;    //==1 表示有命令处理,状态  消息循环中检测,当=1时,需处理cmd内部的命令
char cmd[128];    //需要处理的命令
u8 cjs;    //cjs:cmd命令计数
char *cmds;                //命令解释执行的指针

main函数

int main(void)
{    
    u16 a,b;
    system_init();    //系统初始化
    USART_ENABLE_CMD();        //打开串口命令处理
    while(1)     //主消息循环
    {     
        //---处理上行(上传采集数据)
        if (sec>1){  //定时器中断控制sec变量
            CompADC();    //计算采集AD的平均值    [2]ADI  [1]ADV [0]24V 
            sprintf(buf,"app.da(\"%d|%d|%d\");\r\n",After_filter[2],After_filter[1],After_filter[0]);
            send(buf);
            sec=0;
        }

        //--处理下行命令
        if (iscmdok==1){    //串口接收中断控制iscmdok变量,当此变量=1的时候表示已经完整的传输过来一个cmd命令,该命令在cmd字符串中,参见串口中断程序
            cmds=cmd;    //执行cmd的开始
            while(*cmds!=0){
                //-----------------------------开始进入命令处理--------------------------------------
                if ((*cmds=='D')&(*(cmds+1)=='A')&(*(cmds+2)=='V')){
                    ...... //DAV命令的处理代码
                }
                //----------------
                else if ((*cmds=='D')&(*(cmds+1)=='A')&(*(cmds+2)=='I')){
                    ...... //DAI命令的处理代码
                }
                .....//其他的命令处理代码
                //-----------------------------命令处理结束--------------------------------------
                if (*cmds=='|'){    //有下一条命令需要继续解析
                    cmds++;
                }
                else{    //命令有错误或者解析完成,退出while循环
                    #ifdef DEBUG
                        if (*cmds!=0){
                            sprintf(buf,"err cmd:%s ",cmd);send(buf);
                        }
                    #endif
                    *cmds=0;
                }
            }
            //----命令处理完成--------
            iscmdok=0;    //设置完成标志,以进入下一轮命令处理
        }

    }
}

这是一个主消息结构,可以看到,在一开始进入main函数后,系统执行了system_init(); 在该函数中,系统设置了GPIO、AD、DAC、串口、定时器等单片机的硬件环境,这个我们就详细讲解了,请参见代码

然后系统进入了while(1)组成的消息循环,消息循环分成两个部分,一个处理上行,一个处理下行

上行处理

void TIM14_IRQHandler(void)      //界面刷新
{    //一秒1次
    if(TIM_GetITStatus(TIM14 , TIM_IT_Update) == SET)
    {     sec++;
        TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update); //清中断
    }
}

首先,我们可以看到定时器中断,也就是sec变量会被定时器中断一秒一次的加一,当被加一后,消息中断中就立即执行串口发送命令完成上行处理

下行处理


void USART1_IRQHandler(void)
{    u8    v;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)    //是否接受有数据
    {    
        v=USART_ReceiveData(USART1);  //从PC接受
        //在此书写接收中断处理代码
        if (v=='[')
            {    rjs=0;
                iscmd=1;
            }
            else if(v==']')  //命令接收完毕,存入cmd缓存,设置iscmdok标志,开始执行命令
            {    recv[rjs++]=0;
                iscmd=0;
                for (v=0;v<rjs;v++) cmd[v]=recv[v];
                iscmdok=1;
            }
            else if (iscmd==1)
            {    recv[rjs]=v;
                rjs++;
                if (rjs==sizeof(recv))
                {    iscmd=0;
                    rjs=0;
                }
            }


    }
    if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) //是否有发送数据
    {    
        USART_ClearITPendingBit(USART1, USART_IT_TC);    //???
    }                                 
}

在串口中断程序中,如果串口收到屏幕发来的数据,就会运行该中断函数,并且获取值,通过各种全局变量的状态机机制,我们识别出中括号内还是外,如果在中括号内,则将数据累加到recv数组中,如果遇见了右中括号表示命令接收完毕,此时iscmd=1,并且接受的数据复制到cmd数组中;

在主消息循环中,一直在判断iscmd变量的值,一旦等于1表示有新的命令进来,于是开始执行命令,可以看到执行命令的是一个循环结构,用户可以在此框架中自行扩充或修改命令

一般来说,我们把命令分成两种,传递数值的和传递字符串的,我们写好了相应的处理函数

传递数值的命令
if ((*cmds=='D')&(*(cmds+1)=='A')&(*(cmds+2)=='V')){
    //DAV:1234 命令处理,设置电压
    cmds+=4;  //+=4表示命令有3个字符,此时cmds指向冒号后的第一个字符
    a=getnum();//获取:之后的数值到a
    DAC_updataV(a); //使用a执行命令动作
    #ifdef DEBUG    //调试,输出a
        sprintf(buf,"ok DAV:%d ",a);send(buf);
    #endif                    
}
传递字符串的命令
if ((*cmds=='D')&(*(cmds+1)=='M')&(*(cmds+2)=='O')){
    //DMO  demo命令,本命令无用,纯粹演示一下如何获取字符串
    cmds+=4;//+=4表示命令有3个字符,此时cmds指向冒号后的第一个字符
    getstr();//获取字符串,获取后存在buf中
    #ifdef DEBUG
        send("ok DMO:");send(buf);
    #endif
}