avr实用实验资料Word文档下载推荐.docx
《avr实用实验资料Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《avr实用实验资料Word文档下载推荐.docx(57页珍藏版)》请在冰点文库上搜索。
用户输入区位码或ASCII码即可实现文本显示。
②OCMJ5X10中文液晶显示模块也可用作一般的点阵图形显示器,提供位点阵和字节点阵两种图形显示功能。
用户可在指定的屏幕位置上以点为单位或以字节为单位进行图形显示。
完全兼容一般的图形点阵模块。
③OCMJ5X10中文液晶显示模块可以实现汉字、ASCII码、点阵图形和变化曲线的同屏显示,并可通过字节点阵图形方式造字。
④OCMJ5X10中文液晶显示模块具有上/下/左/右移动当前显示屏幕及清除屏幕的命令,一改传统的使用大量的设置命令进行初始化的方法。
OCMJ5X10中文模块所有的设置初始化工作都是在上电时自动完成的,实现了“即插即用”;
同时,保留了一条专用的复位线供用户选择使用,可对工作中的模块进行软件或硬件强制复位。
规划整齐的10个用户接口命令代码,非常容易记忆。
标准用户硬件接口采用REQ/BUSY握手协议,简单可靠。
⑤OCMJ5X10中文液晶显示模块使用+5V单电源,同时由模块内部提供显示驱动负电压,简化了系统电源的设计。
该模块还具有LED背光源。
OCMJ5X10中文图文液晶显示器的引脚说明如表1所列。
表1OCMJ5X10引脚说明
引
脚
名
称
方
向
说
明
1
VLED-
I
背光源负极(LED-OV)
2
VLED+
背光源正极(LED+5V)
3
VSS
地
4
VDD
(+5V)
5~12
DB0~DB7
数据0~7
13
BUSY
O
=1,已收到数据并正在处理中;
=0,模块空闲,可接收数据
14
REQ
请求信号,高电平有效
15
RES
复位信号,低电平有效
16
NC
17
RT1
LCD灰度调整,外接电阻端
18
RT2
3硬件接口协议及接口时序
OCMJ5X10模块与CPU的接口除了使用DB0~DB7口8根数据线外,仅使用了REQ和BUSY两根控制线,构成请求/应答(REQ/BUSY)握手方式,省略了传统模块接口方式的片选、读写控制、指令/数据选择、使能控制等控制线,从而使硬件接口及软件时序变得非常简单。
在硬件资源十分紧张的应用系统中,也可采用REQ单线延时控制方式,从而把硬件资源占用降至最低。
接口协议如下:
当BUSY线为高电平时(BUSY=1),表示模块忙于内部处理,不能接收用户命令;
而BUSY为低电平时(BUSY=0),表示模块空闲,等待接收用户命令。
CPU可在BUSY为低后的任意时刻开始发送命令。
首先,把用户命令的当前字节放到数据线上,接着发送高电平REQ信号,通知模块,请求处理当前数据线上的命令或数据。
模块在收到外部的REQ高电平信号后,立即读取数据线上的命令或数据,同时将应答线BUSY变为高电平,表明模块已收到数据并正在忙于对此数据的内部处理。
此时,用户对模块的写操作已经完成,可以撤消数据线上的信号并可做模块显示以外的其它工作,也可不断地查询BUSY是否为低。
如果BUSY=0,说明模块对用户的写操作已经执行完毕,可以再送下一个数据。
如向模块发出一个完整的显示汉字的命令,包括显示坐标及汉字代码在内共需5个字节,模块在接收到最后一个字节后,才开始执行整个命令的内部操作;
因此,最后一个字节的应答BUSY高电平(BUSY=1)持续时间较长。
这里以写入汉字命令的时序为例,给出图1所示的OCMJ5X10时序图,对应的具体时间参数说明如表2所列。
表2OCMJ5X10模块时间参数
编
号
参数名称
最小值
最大值
tr/μs
0.4
-
数据线上数据稳定时间
tb/μs
20
最大模块响应时间
trt/μs
11
最小REQ保持时间
ts1/μs
45
最大数据接收时间
5
ts2/ms
30
最大命令指令处理时间
4用户命令
OCMJ5X10模块共有3类10条命令,每条命令分为操作码和操作数两部分,操作数为十六进制数。
下面介绍该模块的用户命令。
(1)显示国标汉字
命令格式F0XXYYQQWW
XX:
以汉字为单位的屏幕行坐标值。
YY:
以汉字为单位的屏幕列坐标值。
QQWW:
坐标位置上要显示的GB2312汉字区位码。
OCMJ5X10模块由于内部含有中文字库,因此中文字符的显示非常简单,只需给出该汉字的区位码即可显示该字。
区位码表可参见GB2312字符集。
(2)显示8×
8ASCII字符
命令格式F1XXYYAS
该命令为4字节命令(最长执行时间为0.8ms,ts2=0.8ms)。
以ASCII码为单位的屏幕行坐标值。
以ASCII码为单位的屏幕列坐标值。
AS:
坐标位置上要显示的ASCII字符码。
(3)显示8×
16ASCII字符
命令格式F9XXYYAS
操作数意义同上。
(4)显示位点阵
命令格式F2XXYY
该命令为3字节命令(最长执行时间为0.1ms,ts2=0.1ms)。
(5)显示字节点阵
命令格式F3XXYYBT
该命令为4字节命令(最长执行时间为0.1ms,ts2=0.1ms)。
(6)清屏
命令格式F4
该命令为单字节命令(最长执行时间为11ms,ts2=11ms),其功能为将屏幕清空。
(7)上移
命令格式F5
该命令为单字节命令(最长执行时间为25ms,ts2=25ms),其功能为将屏幕向上移动一个点阵行。
(8)下移
命令格式F6
该命令为单字节命令(最长执行时间为30ms,ts2=30ms),其功能为将屏幕向下移动一个点阵行。
(9)左移
命令格式F7
该命令为单字节命令(最长执行时间为12ms,ts2=12ms),其功能为将屏幕向左移动一个点阵行。
(10)右移
命令格式F8
该命令为单字节命令(最长执行时间为12ms,ts2=12ms),其功能为将屏幕向右移动一个点阵行。
图2OCMJ5X10液晶显示模块与AT89C52单片机的接口电路
5具体应用
由于OCMJ5X10内部具有中文字库,且使用了简单的两线握手协议,因而将其应用在嵌入式系统中,可简化显示电路的硬件接口设计及软件编程。
虽然模块与单片机之间数据的传输采用并行模式,占用单片机系统的硬件资源相对较多,但是相应显示软件的编制却要比采用串行接口模式的中文字库液晶模块相对简单。
尤其是图形显示界面设计,利用OCMJ5X10提供的显示字节点阵命令(线绘图),可方便、快捷地绘制出显示图形。
此点在绘图速度、ROM空间占用等方面优于串行接口模式的液晶模块。
下面给出OCMJ5X10在嵌入式系统中的具体应用,包括硬件接口电路及软件编程。
5.1硬件接口电路
这里以AT89C52单片机为例,给出OCMJ5X10液晶显示模块与单片机的接口电路。
单片机与模块采用间接控制方式和REQ/BUSY握手方式。
AT89C52的P1.0~P1.7口与模块的DB0~DB7数据线相连,P3.4与模块BUSY线相连,P3.5与模块REQ线相连;
晶振为12MHz,模块采用上电自动复位。
AT89C52与OCMJ5X10的接口电路如图2所示。
5.2显示软件
下面给出与上述硬件电路配套的显示子程序。
其包括初始化、显示汉字、显示8×
16点阵ASCII字符、点绘图及线绘图子程序。
可根据显示需要在主程序的相应位置调用,即可实现相应的显示功能。
OCMJ5X10内部含有GB2312一级字库,可满足绝大部分应用系统汉字显示的需要。
对于一级国标字库内所没有的汉字或需要显示复杂图形时,可通过调用绘点及绘线子程序来实现任意复杂汉字或图形的显示。
;
位定义
BUSYBITP3.4
REQBITP3.5
数据定义
XDATA30H;
屏幕行坐标缓冲区
YDATA31H;
屏幕列坐标缓冲区
DATAHDATA32H;
显示值高位
DATALDATA33H;
显示值低位
初始化子程序
INT:
MOVSP,#60H;
设堆栈
CLRREQ;
请求线清0
SETBBUSY;
将P3.4设为输入口
RET
写模块子程序
SUB1:
JBBUSY,SUB1;
确信模块空闲
MOVP1,A;
向总线送数椐
NOP;
等待数据总线稳定
SETBREQ;
向模块发请求命令
WAIT:
JNBBUSY,WAIT;
等待模块响应
清REQ
RET;
返回
写汉字程序
HZ:
MOVA,#0F0H;
写显示汉字命令
ACALLSUB1
MOVA,X
ACALLSUB1;
写屏幕行坐标值
MOVA,Y
写屏幕列坐标值
MOVA,DATAH
写区位码高位
MOVA,DATAL
写区位码低位
写8×
16ASCII码程序
ASC2:
MOVA,#0F9H;
写显示8×
16ASCII
字符命令
写字符ASCII码
点绘图子程序
HD:
MOVA,#0F2H;
写显示位点阵命令
MOVA,X;
写点屏幕行坐标值
MOVA,Y;
写点屏幕列坐标值
线绘图子程序
HX:
MOVA,#0F3H;
清屏程序
CLR:
MOVA,#0F4H;
写清屏命令
结语
利用OCMJ5X10中文图文液晶模块相对简单的硬件接口及简单的用户命令,可为嵌入式系统设计出显示信息量大且显示信息丰富的全中文人机界面,避免了传统液晶模块中文图形显示界面复杂的硬件接口设计及软件编程。
该模块为嵌入式系统人机界面设计提供了一种较好的解决方案。
部分GCCAVR编译错误(警告)提示及解决方法
1.warning:
passingargument1of'
average'
discardsqualifiersfrompointertargettype
说的是指针不匹配,例如:
我定义了这样一个函数
uint16_taverage(uint16_t*arr)
{
......
}
然后在另一个函数中调用上面的函数
volatileuint16_tADC0_value[18];
//0通道AD,18个数据
volatileuint16_tADC2_value[18];
//2通道AD,18个数据
volatileuint16_tADC3_value[18];
//3通道AD,18个数据
voiddisp_js(void)
Current=(average(&
ADC2_value[0]))/8;
Voltage=(average(&
ADC3_value[0]))/3;
Temperature=average(&
ADC0_value[0]);
当我编译的时候就出
../main.c:
Infunction'
disp_js'
:
28:
warning:
29:
30:
解决方法:
把数组和指针的类型统一起来,volatileuint16_tADC3_value[18];
是具有volatile特性而uint16_taverage(uint16_t*arr)是普通的,去掉volatile就没这个警告了。
2.gccplug-in:
Error:
ObjectfilenotfoundonexpectedlocationE:
\SUNKE\test\DCFD-1\default\DCFD-1.elf
从字面上的意思是就是E:
\SUNKE\test\DCFD-1\default\DCFD-1.elf这个文件没有找到
但是DCFD-1.elf这个文件应该是GCC生成的啊?
他怎么会找不到?
实际引起这个错误的原因多数都是定义变量时出现了错误,比如:
重复定义。
解决方法:
找到错误的变量删除或修改。
3.../modbus.h:
10:
'
Crc_counter'
initializedanddeclared'
extern'
出现这个警告是因为在头文件中给变量赋值了.
例如:
我在头文件中定义
externuint8_tCrc_counter=0;
//com0校验计数器
我在程序文件中定义了
uint8_tCrc_counter=0;
编译的时候就出
.../modbus.h:
在头文件中改成externuint8_tCrc_counter;
//com0校验计数器就可以了
4.../modbus.c:
error:
conflictingtypequalifiersfor'
Uart0_rev_comflag'
../modbus.h:
9:
previousdefinitionof'
washere
出现这个错误提示是因为重复给变量赋值了
.../modbus.c:
这个错误和上面3的警告是一个事,解决方法一样
5.../modbus.c:
previousdeclarationof'
在头文件中和程序文件中定义的变量类型不一致
volatileuint8_tCrc_counter;
都定义成带volatile的或都不带volatile的.
CC过渡到GCC的发现:
GCC中字符串sting默认为signedchar类型数组
Write_Data_String(2,0,"
LCD1602DEMO"
);
//在第一行第2列开始显示
Write_Data_String(1,1,"
MyisLinglong"
//在第二行第1列开始显示
函数原型:
voidWrite_Data_String(unsignedcharx,unsignedchary,uchar*data)
警告提示如下:
main.c:
117:
pointertargetsinpassingargument3of'
Write_Data_String'
differinsignedness
118:
differinsignedness
从ICC过渡到GCC时发现这个奇怪的警告,把ICC中的程序移植到GCC中怎么会出现这么奇怪的现象呢,怪!
!
后来通过N次的XX谷歌才发现原来GCC中默认把string当signedchar.跟我的函数参数uchar(unsignedchar)不一样。
注:
char*
、unsignedchar*、signedchar*是三种不同类型的指针。
修改后的函数为:
voidWrite_Data_String(unsignedcharx,unsignedchary,constchar*data)
这就解决了上面的警告问题。
尽管这个警告对程序运行的效果没有起到破坏作用,但是作为一个严谨的程序员还感觉不爽。
另外,建议大家抛弃#defineucharunsignedchar
#defineuint
unsignedint,也许你在某某视频里学到了这一点,其实当你编程能力到达一定水平后,你就会发现不简略而是选择完整的写法很好的,编译器可以高亮显示unsignedcharunsignedint这对你阅读程序很有帮助的。
GCC中关于中断修改全局变量以及volatile的用法
在GCC编译器中,如果定义了全局变量而没有在定义时加上volatile的话,编译器编译时会进行优化的,不能做到中断服务程序中修改定义的变量,必须在定义时加上volatile才可以达到修改全局变量的目的…
unsignedcharnum=0;
.....
INTERRUPT()
{
....
num++;
}
voidmain()
out(num);
很不幸的事情是在主函数中,num一直都不会变,编译器avrstdio,外部中断。
调试中发现中断时可以进去的,然而中断出来以后,这个全局变量就被改变了,后来加了volitale就可以了。
。
下面说说volitale的具体用法(以下内容都是摘抄):
volatile的字面意思为“不稳定的,易变的”
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。
没有用volatile关键字声明的变量i在被访问的时候可能直接从cpu的寄存器中取值(因为之前i被访问过,也就是说之前就从内存中取出i的值保存到某个寄存器中),之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。
以上两种情况的区别在于被编译成汇编代码之后,两者是不一样的。
之所以这样做是因为变量i可能会经常变化,保证对特殊地址的稳定访问。
来源:
(