本帖最后由 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发现如果在一个函数中用多个delay(),会编译不过去,只能有一个,希望老师、大叔和大家继续指点
|