[LOOK] 【M0第5帖||LOOK第三帖】mmbox详解和1602显示类实现

[复制链接]
3608|11
 楼主| nixianmin 发表于 2011-9-29 20:38 | 显示全部楼层 |阅读模式
Box, mb, CD, LCD, pi
本帖最后由 nixianmin 于 2011-9-29 21:23 编辑

好郁闷,刚才编辑了大半个小时的帖子奔溃了,什么都没留下,又得重写:'(

    1602的参考了 cat_li的程序 https://bbs.21ic.com/icview-268051-1-1.html
    mmbox<T,SIZE>是个多重消息邮箱,其中T的类型只能是32位的数据类型,昨天也问老师原因了,是因为mbox_t的基类是mbox_base_t,mbox_base_t的代码逻辑是固定的,只能处理一种“宽度”的数据类型,mmbox也是一样,想要处理其他类型则需要自己去修改基类了。



下面贴上程序的主要代码,代码主要是讲一个任务和一个中断函数,中断函数是将接收的字符、字符串存到邮箱里,而任务是从邮箱里获取消息,并将获取的消息通过1602显示出来。这任务里用到了get函数,该函数当邮箱里有消息时,则读取消息,若没有消息则任务进入堵塞状态,只有当中断将消息存到邮箱才能使任务唤醒。
  1. /***************************************
  2. //
  3. ***************************************/
  4. void task2_uart0_c::routine()
  5. {
  6.         uart0.Uart0RxEnableInt();  //使能接受中断
  7.         lcd1602_c lcd1;
  8.         uint8_t lcd_x=0;
  9.         lcd1.Lcd_WString(0,0,"Receive data:");

  10.         while(true){
  11.                 #ifdef _DEBUG_
  12.                         uart0.Wstr("before uart_megs");
  13.                 #endif
  14.                 uint32_t msg=uart_megs.get();
  15.                 uart0.Wstr("接收的内容:");
  16.                 if(msg!='\n')
  17.                 {
  18.                         if(lcd_x==16)
  19.                                 lcd_x=0;
  20.                         lcd1.Lcd_WByte(lcd_x++,1,msg);
  21.                 }
  22.                 else
  23.                 {
  24.                         lcd1.Lcd_WString(0,1,"                ");        
  25.                         lcd_x=0;
  26.                 }
  27.                 uart0.Write(&msg,1);          //发送接收的数据
  28.     uart0.Wstr("\n");

  29.         }
  30. }

  31. void uart0_int_c::dsr(int vector, uintptr_t count)
  32. {
  33.         uint32_t buf=0;
  34.         if(UART0s.ISR.Bits.RDA_INT==1)
  35.         {
  36.                 #ifdef _DEBUG_
  37.                         uart0.Wstr("Into uart0 dsr\n");
  38.                 #endif
  39. //                do{
  40.                    buf=UART0s.DATA.Regs;
  41.                 task2_uart0.uart_megs.do_tryput(buf);        //读取接收的数据
  42. //      task2_uart0.uart_megs.do_tryput('a');        
  43. //                }while(UART0s.ISR.Bits.RDA_IF!=0);        
  44.         }
  45.                
  46. }
在调试的过程中,我发现如果发送的是字符串,那么程序会先将所有接收的字符先存到邮箱,再进入任务,应该是连续中断吧。而且读取邮箱消息时是先存的消息先读出来,应该是队列的结构。

这种方式在处理工业的一些串口协议中很有用,我最近就在写和表通信的协议用430,那个程序写的很差,对接收到的所有字符的判断和处理都处在中断里进行。如果像LOOK就可以将一个任务和一个中断,任务在没有消息时被阻塞,当中断接收数据时可以整条命令都存到邮箱里(不用像我现在一个个字符处理,且很乱),任务进入到就绪态,运行到该任务就可以将邮箱里的消息全部读取出来再处理,处理结束任务就有进入阻塞状态,感觉比我那样不知清晰多少。以后看点源码,自己实现个小的,在没有系统用时可以自己写。

废话说多了,下面把1602的类和程序都贴上:
1602.h
  1. /*****************************************
  2. //1602显示控制类
  3. //不能和LED对象共存
  4. ******************************************/
  5. #ifndef _LCD1602_H_
  6. #define _LCD1602_H_

  7. /**********************************
  8. //一个LCD1602的操作类
  9. //
  10. **********************************/
  11. class lcd1602_c{
  12. public:
  13.         lcd1602_c();
  14.         void Lcd_WByte(uint8_t,uint8_t,int8_t);        //写一个字
  15.         void Lcd_WString(uint8_t,uint8_t,const char * ); //写字符串
  16.         void Lcd_SetXY(uint8_t,uint8_t);

  17. private:
  18.         void Lcd_Wdata(int32_t );
  19.         void Lcd_Wcom(int32_t );
  20.         void LcdDelay(unsigned char);

  21. };



  22. #endif
1602.cpp
  1. /*****************************************
  2. //
  3. //
  4. ******************************************/
  5. #include <NUC1xx.h>
  6. #include"NUC1xxM051Seriescfg.h"
  7. #include"main.h"
  8. #include"LCD1602.H"

  9. #define INIT_LCD_PORT() GPIOEs.PMD.Bits.PMD5=1;\
  10.                                                 GPIOCs.PMD.Bits.PMD14=1;\
  11.                                                 GPIOCs.PMD.Bits.PMD15=1;\
  12.                                                 GPIOCs.PMD.Bits.PMD7=1;\
  13.                                                 GPIOCs.PMD.Bits.PMD6=1;\
  14.                                                 GPIOAs.PMD.Regs|=0X00155550 //gpa2~gpa9


  15. #define GPE_GROUND()        GPIOEs.DOUT.Bits.Pin5=0
  16. #define LCD_V0_CLR()        GPIOCs.DOUT.Bits.Pin14=0
  17. //使能位
  18. #define LCD_EN_SET()        GPIOCs.DOUT.Bits.Pin7=1
  19. #define LCD_EN_CLR()        GPIOCs.DOUT.Bits.Pin7=0
  20. //读写位控制
  21. #define LCD_RW_R()        GPIOCs.DOUT.Bits.Pin6=1
  22. #define LCD_RW_W()        GPIOCs.DOUT.Bits.Pin6=0
  23. //数据命令位
  24. #define LCD_RS_DATA()        GPIOCs.DOUT.Bits.Pin15=1
  25. #define LCD_RS_CMD()        GPIOCs.DOUT.Bits.Pin15=0

  26. #define LCD_DATA(DATA) GPIOAs.DOUT.Regs=(DATA<<2)        
  27. //////////////////////////////命令/////////////////////////////////////
  28. #define                        CMD_CLR                0x01             // 清除屏幕
  29. #define                        CMD_BCK                0x02             // DDRAM回零位
  30. #define                        CMD_DEC1                0x04             // 读入后AC(指针)减1,向左写
  31. #define                        CMD_ADD1                0x06             // 读入后AC(指针)加1,向右写
  32. #define                        CMD_DIS1                0x0f             // 开显示_开光标_开光标闪烁
  33. #define                        CMD_DIS2                0x0e             // 开显示_开光标_关光标闪烁
  34. #define                        CMD_DIS3                0x0c             // 开显示_关光标_关光标闪烁
  35. #define                        CMD_DISOFF                0x08             // 关显示_关光标_关光标闪烁
  36. #define                        CMD_SET2                0x38             // 8位总线_2行显示

  37. lcd1602_c::lcd1602_c()
  38. {

  39.         GPE_GROUND();  
  40.         LCD_V0_CLR();
  41.         Lcd_Wcom(CMD_SET2);        
  42.         Lcd_Wcom(CMD_SET2);
  43.         LcdDelay(10);
  44.         Lcd_Wcom(CMD_DIS1);//开显示
  45.         LcdDelay(10);
  46.         Lcd_Wcom(CMD_CLR);//清屏
  47. }
  48. //写数据
  49. void lcd1602_c:cd_Wdata(int32_t data)
  50. {
  51.         LCD_RS_DATA();
  52.         LCD_RW_W();
  53.         LcdDelay(1);
  54.         LCD_DATA(data);
  55.         LCD_EN_SET();
  56.         LcdDelay(1);
  57.         LCD_EN_CLR();
  58. }
  59. //写命令
  60. void lcd1602_c:cd_Wcom(int32_t com)
  61. {
  62.         LCD_RS_CMD();
  63.         LCD_RW_W();
  64.         LcdDelay(1);
  65.         LCD_DATA(com);
  66.         LCD_EN_SET();
  67.         LcdDelay(1);
  68.         LCD_EN_CLR();
  69. }           

  70. void lcd1602_c:cd_SetXY(uint8_t x,uint8_t y)
  71. {
  72.         if(y == 0)
  73.         {
  74.                 Lcd_Wcom(0x80+x);        // 第一行
  75.         }else{
  76.                 Lcd_Wcom(0xC0+x);        // 第二行
  77.         }
  78. }
  79. //写一个字节
  80. void lcd1602_c:cd_WByte(uint8_t x,uint8_t y,int8_t dbyte)
  81. {
  82.          Lcd_SetXY(x,y);
  83.          Lcd_Wdata(dbyte);
  84. }

  85. void lcd1602_c:cd_WString(uint8_t x,uint8_t y,const char *pstr)
  86. {
  87.         Lcd_SetXY(x,y);
  88.         do{
  89.                 Lcd_Wdata(*pstr++);
  90.         }while(*pstr!=0);
  91. }

  92. void lcd1602_c:cdDelay(unsigned char n)
  93. {
  94.         volatile unsigned int  i;

  95.          for(;n>0;n--)
  96.          {
  97.             for(i=0;i<980;i++);
  98.          }
  99.          
  100. }
发现如果在一个函数中用多个delay(),会编译不过去,只能有一个,希望老师、大叔和大家继续指点

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| nixianmin 发表于 2011-9-29 21:47 | 显示全部楼层
本帖最后由 nixianmin 于 2011-9-29 21:49 编辑

唉,破网速,终于上传好了,图片用破手机拍的,大家勉强看看
1602的第2行显示的是串口发的数据,发送换行符能把第2行显示清掉,
不然每次发送的数据都是显示在上次的后面

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
john_lee 发表于 2011-9-29 23:00 | 显示全部楼层
嗯,关于这个delay()函数,很普通的,就是个函数而已,随便用,我还真没遇见过楼主发现的问题,确实很奇怪。
 楼主| nixianmin 发表于 2011-9-29 23:30 | 显示全部楼层
3# john_lee 嗯,谢谢老师,不知道是不是设置问题,不纠结这个,先写出来再说
hotpower 发表于 2011-9-29 23:54 | 显示全部楼层
不错~~~LOOK很好用的
Swallow_0322 发表于 2011-9-30 07:37 | 显示全部楼层
顶啊!
tao560532 发表于 2011-9-30 09:44 | 显示全部楼层
 楼主| nixianmin 发表于 2011-10-3 12:46 | 显示全部楼层
自己顶下,十一玩了会,等会继续写点
weshiluwei6 发表于 2011-10-26 19:25 | 显示全部楼层
看看 1602的 我的怎么不能显示
weshiluwei6 发表于 2011-10-26 19:25 | 显示全部楼层
看起来比较麻烦 是LOOK啊
 楼主| nixianmin 发表于 2011-10-27 18:17 | 显示全部楼层
10# weshiluwei6 只要连接对了,好事比较好些的,我参考的帖子里有连接图
weshiluwei6 发表于 2011-10-30 11:09 | 显示全部楼层
恩 谢谢啦 嘿嘿 11# nixianmin
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:电机控制,TI InstaSpin Foc交流群:335663930

40

主题

431

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部