打印

51基于实时系统的编程

[复制链接]
5993|52
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhouwenbin1989|  楼主 | 2011-3-27 23:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近学习small rtos51,在51开发板上弄了个带密码登陆的液晶时钟,可是在密码登陆时总有个问题解决不了。问题描述:当输入错误密码后想删除显示在1602上的全部星号(也就是在1602上连写6个空格),删除完了就出问题了。接下来在输入密码可能会导致无**常显示,很难复位有时只有电源启动。一个一个删除又没有问题。想了好久都没明白为什么?除掉这个功能一切正常。

相关帖子

沙发
ayb_ice| | 2011-3-28 08:28 | 只看该作者
这和RTOS没有关系

使用特权

评论回复
板凳
zhouwenbin1989|  楼主 | 2011-3-28 12:24 | 只看该作者
2# ayb_ice
个人感觉好像是定时器问题,我定时中断10ms,感觉写字符串函数回超过10ms,写的过程是关中断。感觉开中断后定时器处理会出问题。有个问题问:EA=0.TR0=1,ET0=1,时,定时计数器会正常计数吗?只是不响应中断而已。也就是说如果计数器设置为1000,计数器计数到500时EA=0;去处理一段程序,处理完回来后计数器的值还是500吗?

使用特权

评论回复
地板
zhouwenbin1989|  楼主 | 2011-3-28 12:30 | 只看该作者
还有个问题好像只要拔掉串口下载电源线在插上,程序运行也不正常。只有在重启一次电源开关。才能正常。而且你在不正常是按下的键会在下一次打开电源启动时在1602上显示出来。太奇怪了。现在就是一个问题还没解决又有新问题,希望有高手能给点建议给我。谢谢了

使用特权

评论回复
5
ayb_ice| | 2011-3-28 13:29 | 只看该作者
只要TR0=1就会计时的,如果开了中断,TF0=1时会响应中断

使用特权

评论回复
6
zhouwenbin1989|  楼主 | 2011-3-28 14:09 | 只看该作者
5# ayb_ice
谢了。按键消息和1602命令两个消息队列都存储在XDATA,程序出问题按得键没有响应,重新上电响应了之前的按键,也就是说之前的按键存进了按键消息队列,但是没有正确传送到1602命令队列,重新上电后按键消息队列里的消息好像断电保存了一上电就传送到1602命令队列里。所以即使没按键1602也自己操作起来了。我想问难道断电XDTA里的数据可以保存?

使用特权

评论回复
7
ayb_ice| | 2011-3-28 14:45 | 只看该作者
你要看你断多久了,也和程序有关的,比如你复位后会清零XRAM

使用特权

评论回复
8
zhouwenbin1989|  楼主 | 2011-3-29 12:06 | 只看该作者
7# ayb_ice
XRAM断电不是会自动清除所有数据吗?

使用特权

评论回复
9
chrishardy| | 2011-3-29 12:10 | 只看该作者
除掉后功能正常肯定不是RTOS的问题了 看看你的键盘输入程序是否不够完善吧

使用特权

评论回复
10
zhouwenbin1989|  楼主 | 2011-3-29 12:42 | 只看该作者
RTOS肯定没问题啊,我感觉是写字符串时间长了,一般按键去抖延时个20ms加上扫描处理也就20几ms但1602写一个字符都不止20MS。这里该怎么处理好啊?感觉应该出乱的结果应该是不可预测的,但是每次都是在那个固定的时候出问题。

使用特权

评论回复
11
刘前辈| | 2011-3-30 10:21 | 只看该作者
没那么复杂。LZ的功能裸奔都能做,(书上有现成的裸奔程序)RTOS应该更简单了。

还是自己没用好RTOS。

使用特权

评论回复
12
ayb_ice| | 2011-3-30 10:58 | 只看该作者
small rtos的实时性是很差的,比tiny都差远了,处理系统中断时是关掉中断的,或将系统中断设为最高优先级,而在TINY里系统中断根本不占用中断优级,其实是扩展了中断优级,仅比任务的优先级要高,而低于所有标准中断

使用特权

评论回复
13
zhouwenbin1989|  楼主 | 2011-3-30 13:24 | 只看该作者
11# 刘前辈
裸的我做过了,只是最近看了small rtos才想试试用系统的怎么样。之前编的程序都没用消息队列,这次试下消息队列程序,就出问题了,还是一串一串的问题

使用特权

评论回复
14
zhouwenbin1989|  楼主 | 2011-3-30 13:31 | 只看该作者
#include "config.h"
#define Self_Define_Isp_Download_Command 0x3d
#define Datecom P0
sfr IAP_CONSTR=0xe7;
sbit E=P2^7;                //1602使能引脚
sbit RW=P2^6;                //1602读写引脚       
sbit RS=P2^5;                //1602数据/命令选择引脚
uint8 Showtime[4];
uint8 Showtimedis[4];
uint8 Password[7];
char Keytemp[1];
uint8 addr=9;
uint8 code table[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};//数码管编码表管编码表
char code Passnumber[7]={2,1,2,2,0,9,'\0'};
uint8 OS_Q_MEM_SEL KeyValueBuf[8];
uint8 OS_Q_MEM_SEL Command1602Buf[8];
void main(void)
{
        TMOD = (TMOD & 0XFF) | 0X21;
        SM0=0;
        SM1=1;
        REN=1;
        TH1=0xfd;
        TL1=0xfd;
        ES=1;
        TR1=1;
        TL0 = 0x00;          //时钟节拍10ms
        TH0 = 0xDC;
        TR0 = 1;
        ET0 = 1;
        Lcd_Init();  //运行55ms
       OSStart();        //运行1ms
}
             void KeyInput(void) //扫描按键,正确按键后将按键信息加入消息队列KeyValueBuf供别的任务处理
{
    uint8 temp;
        OSQCreate(KeyValueBuf,8);  //创建按键值消息队列,占用8字节
        //OSWait(K_TMO,1);
        while (1)
    {
          P1=0xf0;
          OSWait(K_TMO,2);   //等待P1口数据稳定
          if(P1!= 0xf0)
           {
           OSWait(K_TMO,2); //延时20ms去抖
           if(P1!=0xf0)
                {
             temp=Keyscan();
             OSWait(K_TMO,2); //延时20ms去抖
             if(temp==Keyscan())       
           {
                    while(temp==Keyscan()) ;         //松手检测
                    OSQPost(KeyValueBuf,temp);  //正确按键后发送按键消息
                   }
                }          
          }        
    }      
}         

           void KeyHandle(void)          //根据按键消息队列信息实时处理
{  static uint8  i=0;
   uint8  j;
   OSQCreate(Command1602Buf,8);        //建立1602命令消息队列
   //OSWait(K_TMO,100);
   while(1)
   {
           OSQPend(Keytemp,KeyValueBuf,0);          //等待按键值消息队列有消息,读取
        if((Keytemp[0])<=9&&(Keytemp[0])>=0)//0~9号键,即输入正确数字,1602向后写个“*”
         {        Password[6]='\0';
            Password[i++]=Keytemp[0];
                //P2=Password[i-1];
                 OSQPost(Command1602Buf,WRITE_STAR); //根据按键值向命令1602消息队列发送实时处理命令       
         }
         else if(Keytemp[0]==0x0a)        //按下10号按键即向前删除一个“*”
         {
                Password[--i]=0;
                //delay1();
                OSQPost(Command1602Buf,DEL_STAR);
         }
         else if(Keytemp[0]==0x0b)        //按下11号按键即删除全部“*”.问题就出在这。
         {
                for(j=0;j<6;j++)
                Password[j]=0;
                //delay1();
                OSQPost(Command1602Buf,CLR_ALLSTAR);
         }
         else if(Keytemp[0]==0x0c)        //按下12号确认输入显示“#”
         {
                 OSQPost(Command1602Buf,ENTERPASS);
                continue;
         }
   }
}
          void  Enter1602(void)  //1602密码登陆界面处理
{
   uint8 temp[1];
   OSSemCreate(LCD1602_SEM,0);
   Write_string(1,1,"  -SMALL RTOS-  "); //1602初始化登陆界面大概要写250ms
   OSWait(K_TMO,2);
   Write_string(2,1,"Password:");
  while(1)
   {
    OSQPend(temp,Command1602Buf,0);
        switch (temp[0])
         {       
                 case(WRITE_STAR):  //在1602上写下一个“*”号,密码为六位
                                  if(addr<9&&addr>=15)
                                                     addr=9;
                                  else
                                                     {addr+=1;Write_char(2,addr,'*');}break;//写一个字符大概30ms
                 case(DEL_STAR):   //删除当前地址“*”
                                 if(addr>9&&addr<16)
                                                 {
                                                   Write_char(2,addr,' ');
                                                   addr-=1;
                                                 }break;
                 case(CLR_ALLSTAR):  //删除所有星号,问题就出在这了。只要按下这个键一会就出问题了
                                  addr=9;
                                                  Write_string(2,10,"       ");
                                                  break;
                 case(ENTERPASS):  //输入一个'#',即确定键
                                 Write_char(2,16,'#');
                                                 if(!strcmp(Password,Passnumber))
                                                 {
                                                   Write_string(2,1," hello welcome   ");
                                                   OSWait(K_TMO,OS_TICKS_PER_SEC )
                                                 }
                                                 else
                                                     {
                                                      Write_string(2,1," sorry error    ");
                                                          OSWait(K_TMO,OS_TICKS_PER_SEC );
                                                      Write_string(2,1,"Password:");
                                                          }
                                                 break;
                 default:break;
         }          
         //OSWait(K_TMO,50);
   }

}




void delay1()                 //延时1毫秒
{
  uint8 y;
  for(y=100;y>0;y--);
}
void delay()        //延时140US液晶屏时序需要
{
        uint8 i,j;
        for(i=0; i<=100; i++)
        for(j=0; j<=20; j++)
;
}
void Write_Command(uint8 c)           //写命令指令函数
{
  //OS_ENTER_CRITICAL();
  Datecom=c;
  RS=0;
  RW=0;
  E=0;        //这里写的时序很重要啊,时序不多很难正确写进去啊
  delay();
  E=1;
  delay();
  //OS_EXIT_CRITICAL();
}
void Write_Date(uint8 c)                   //写数据函数
{
  //OS_ENTER_CRITICAL();
  Datecom=c;
  RW=0;
  RS=1;
  E=0;
  delay();
  E=1;
  delay();
  //OS_EXIT_CRITICAL();
}
void Write_char(uint8 hang,uint8 lie,uint8 c)   //写字符型数据函数
{
  //OS_ENTER_CRITICAL();
  if(hang==1)Write_Command(0x80+lie-1);
  if(hang==2)Write_Command(0xc0+lie-1);
  Write_Date(c);
//delay1();
  //OS_EXIT_CRITICAL();
  }
void Write_string(uint8 hang,uint8 lie,uint8 *p)  //写字符串函数
{
  //OS_ENTER_CRITICAL();         
  if(hang==1)Write_Command(0x80+lie-1);
  if(hang==2)Write_Command(0xc0+lie-1);
  while(*p!='\0')
  {
   Write_Date(*(p++));          
   delay1();
  }
  //OS_EXIT_CRITICAL();
}
void Lcd_Init()                //1602初始化
{
   Write_Command(0x01);  //清屏指令
   Write_Command(0x38);         //设置16*2显示,5*7点阵,8位数据接口
   Write_Command(0x0c);         //开显示,光标不显示,不显示光标
   Write_Command(0x06);        //当读写一个字符后地址指针光标都加一          
}

uint8 Keyscan(void)   //矩阵扫描函数,返回扫描到的键值
{
  uint8 i,j,temp,Buff[4]={0xfe,0xfd,0xfb,0xf7};
  OS_ENTER_CRITICAL();
  for(j=0; j<4; j++)
        {
                P1 = Buff[j];
                /*以下三个_nop_();作用为让 P1 口的状态稳定*/
             delay();
                temp = 0x10;                                                                                                                                                                    
                for(i=0; i<4; i++)
                {
                        if(!(P1 & temp))
                        {
                            OS_EXIT_CRITICAL();
                                return (i+j*4);
                        }
                        temp <<= 1;
                }       
        }
  OS_EXIT_CRITICAL();
  return 0xff;
}
void UART_Interrupt_Recieve(void) interrupt 4  //STC下载不断电串口程序
{
   unsigned char k=0;
   unsigned int a,b;
   if(RI==1)
   {
      RI=0;
      k=SBUF;
      if(k==Self_Define_Isp_Download_Command)
       {
         for(a=1010;a>0;a--)
            for(b=100;b>0;b--)        ;
         IAP_CONSTR=0x60;
        }
   }
    else
     {
      TI=0;
     }

}




这是我的程序,希望哪位大侠有空帮看看。

使用特权

评论回复
15
zhouwenbin1989|  楼主 | 2011-3-30 13:32 | 只看该作者
12# ayb_ice
他的实时性还很差。我没怎么接触过别的实时系统,这是我接触的第一个系统。这方面还不怎么了解,TINY哪有全部源代码

使用特权

评论回复
16
ayb_ice| | 2011-3-30 13:59 | 只看该作者
中断的实时性是最高的
RTOS都有临界代码,会关中断,所以RTOS的一个重要指标是中断延时,这个时间越短越好,而small rtos51这个延时是很大的,远比TINY要大
典型的small rtos51用来学习可以,做项目还是不好的

使用特权

评论回复
17
ayb_ice| | 2011-3-30 14:00 | 只看该作者
队列和RTOS其实没有关系,裸奔也可以用的

使用特权

评论回复
18
刘前辈| | 2011-3-30 17:25 | 只看该作者
本帖最后由 刘前辈 于 2011-3-30 17:35 编辑

很简单。执行下面程序时,把时间片功能临时关闭就行了。——关调度而不是关中断。系统节拍照常跳动。
else if(Keytemp[0]==0x0b)     //按下11号按键即删除全部“*”.问题就出在这。
         {
                for(j=0;j<6;j++)
                Password[j]=0;
                //delay1();
                OSQPost(Command1602Buf,CLR_ALLSTAR);
         }


或者,利用信号量,保护这段程序互斥执行。

或者,把系统节拍放大到50ms。

这属于“一个系统任务,是同步的还是并发的?”问题。显然这一段是需要同步执行的,也就是资源保护问题。——它不希望被时间片切换并发执行。





使用特权

评论回复
19
zhouwenbin1989|  楼主 | 2011-3-30 22:08 | 只看该作者
本帖最后由 zhouwenbin1989 于 2011-3-30 22:11 编辑

18# 刘前辈
谢谢前辈啊,找个时间试试。可是为什么其它按键也是这样处理的没问题。再请教前辈一个问题keil c51中局部变量在寄存器用完后分配在固定地址怎么理解,是在DATA,IDATA,XDATA哪一块中。small rtos是如何改变这种存储的,汇编吗?

使用特权

评论回复
20
zhouwenbin1989|  楼主 | 2011-3-30 22:08 | 只看该作者
16# ayb_ice
请问在哪可以得到TINY的全部源代码?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:在路上。人的一生很短,但是如果卑劣的过这一生,那么就太长了。

0

主题

112

帖子

1

粉丝