本帖最后由 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(),会编译不过去,只能有一个,希望老师、大叔和大家继续指点 |