打印
[LOOK]

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

[复制链接]
2765|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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函数,该函数当邮箱里有消息时,则读取消息,若没有消息则任务进入堵塞状态,只有当中断将消息存到邮箱才能使任务唤醒。
/***************************************
//
***************************************/
void task2_uart0_c::routine()
{
        uart0.Uart0RxEnableInt();  //使能接受中断
        lcd1602_c lcd1;
        uint8_t lcd_x=0;
        lcd1.Lcd_WString(0,0,"Receive data:");

        while(true){
                #ifdef _DEBUG_
                        uart0.Wstr("before uart_megs");
                #endif
                uint32_t msg=uart_megs.get();
                uart0.Wstr("接收的内容:");
                if(msg!='\n')
                {
                        if(lcd_x==16)
                                lcd_x=0;
                        lcd1.Lcd_WByte(lcd_x++,1,msg);
                }
                else
                {
                        lcd1.Lcd_WString(0,1,"                ");        
                        lcd_x=0;
                }
                uart0.Write(&msg,1);          //发送接收的数据
    uart0.Wstr("\n");

        }
}

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

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

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

/**********************************
//一个LCD1602的操作类
//
**********************************/
class lcd1602_c{
public:
        lcd1602_c();
        void Lcd_WByte(uint8_t,uint8_t,int8_t);        //写一个字
        void Lcd_WString(uint8_t,uint8_t,const char * ); //写字符串
        void Lcd_SetXY(uint8_t,uint8_t);

private:
        void Lcd_Wdata(int32_t );
        void Lcd_Wcom(int32_t );
        void LcdDelay(unsigned char);

};



#endif
1602.cpp
/*****************************************
//
//
******************************************/
#include <NUC1xx.h>
#include"NUC1xxM051Seriescfg.h"
#include"main.h"
#include"LCD1602.H"

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


#define GPE_GROUND()        GPIOEs.DOUT.Bits.Pin5=0
#define LCD_V0_CLR()        GPIOCs.DOUT.Bits.Pin14=0
//使能位
#define LCD_EN_SET()        GPIOCs.DOUT.Bits.Pin7=1
#define LCD_EN_CLR()        GPIOCs.DOUT.Bits.Pin7=0
//读写位控制
#define LCD_RW_R()        GPIOCs.DOUT.Bits.Pin6=1
#define LCD_RW_W()        GPIOCs.DOUT.Bits.Pin6=0
//数据命令位
#define LCD_RS_DATA()        GPIOCs.DOUT.Bits.Pin15=1
#define LCD_RS_CMD()        GPIOCs.DOUT.Bits.Pin15=0

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

lcd1602_c::lcd1602_c()
{

        GPE_GROUND();  
        LCD_V0_CLR();
        Lcd_Wcom(CMD_SET2);        
        Lcd_Wcom(CMD_SET2);
        LcdDelay(10);
        Lcd_Wcom(CMD_DIS1);//开显示
        LcdDelay(10);
        Lcd_Wcom(CMD_CLR);//清屏
}
//写数据
void lcd1602_c:cd_Wdata(int32_t data)
{
        LCD_RS_DATA();
        LCD_RW_W();
        LcdDelay(1);
        LCD_DATA(data);
        LCD_EN_SET();
        LcdDelay(1);
        LCD_EN_CLR();
}
//写命令
void lcd1602_c:cd_Wcom(int32_t com)
{
        LCD_RS_CMD();
        LCD_RW_W();
        LcdDelay(1);
        LCD_DATA(com);
        LCD_EN_SET();
        LcdDelay(1);
        LCD_EN_CLR();
}           

void lcd1602_c:cd_SetXY(uint8_t x,uint8_t y)
{
        if(y == 0)
        {
                Lcd_Wcom(0x80+x);        // 第一行
        }else{
                Lcd_Wcom(0xC0+x);        // 第二行
        }
}
//写一个字节
void lcd1602_c:cd_WByte(uint8_t x,uint8_t y,int8_t dbyte)
{
         Lcd_SetXY(x,y);
         Lcd_Wdata(dbyte);
}

void lcd1602_c:cd_WString(uint8_t x,uint8_t y,const char *pstr)
{
        Lcd_SetXY(x,y);
        do{
                Lcd_Wdata(*pstr++);
        }while(*pstr!=0);
}

void lcd1602_c:cdDelay(unsigned char n)
{
        volatile unsigned int  i;

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

LOOK上的1602类加MMBOX.rar

1016.99 KB

相关帖子

沙发
nixianmin|  楼主 | 2011-9-29 21:47 | 只看该作者
本帖最后由 nixianmin 于 2011-9-29 21:49 编辑

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

20110929.jpg (128.78 KB )

20110929.jpg

20110929(001).jpg (121.97 KB )

20110929(001).jpg

使用特权

评论回复
板凳
john_lee| | 2011-9-29 23:00 | 只看该作者
嗯,关于这个delay()函数,很普通的,就是个函数而已,随便用,我还真没遇见过楼主发现的问题,确实很奇怪。

使用特权

评论回复
地板
nixianmin|  楼主 | 2011-9-29 23:30 | 只看该作者
3# john_lee 嗯,谢谢老师,不知道是不是设置问题,不纠结这个,先写出来再说

使用特权

评论回复
5
hotpower| | 2011-9-29 23:54 | 只看该作者
不错~~~LOOK很好用的

使用特权

评论回复
6
Swallow_0322| | 2011-9-30 07:37 | 只看该作者
顶啊!

使用特权

评论回复
7
tao560532| | 2011-9-30 09:44 | 只看该作者
帅气

使用特权

评论回复
8
nixianmin|  楼主 | 2011-10-3 12:46 | 只看该作者
自己顶下,十一玩了会,等会继续写点

使用特权

评论回复
9
weshiluwei6| | 2011-10-26 19:25 | 只看该作者
看看 1602的 我的怎么不能显示

使用特权

评论回复
10
weshiluwei6| | 2011-10-26 19:25 | 只看该作者
看起来比较麻烦 是LOOK啊

使用特权

评论回复
11
nixianmin|  楼主 | 2011-10-27 18:17 | 只看该作者
10# weshiluwei6 只要连接对了,好事比较好些的,我参考的帖子里有连接图

使用特权

评论回复
12
weshiluwei6| | 2011-10-30 11:09 | 只看该作者
恩 谢谢啦 嘿嘿 11# nixianmin

使用特权

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

本版积分规则

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

40

主题

431

帖子

6

粉丝