
姓名: 徐娇: 17011210547
来自
【牛介绍】
C语言是一种广泛使用的通用计算机编程语言. C语言的设计目标是提供一种编程语言,该语言可以通过简单的方式进行编译,处理低级内存,生成少量机器代码并且可以在任何操作环境都不支持的情况下运行.
尽管C语言提供了许多底层处理功能,但它仍保持了良好的跨平台特性. 用标准规范编写的C语言程序可以在许多计算机平台上编译,甚至包括某些嵌入式处理器. (SCM或MCU)以及超级计算机和其他操作平台.
在1980年代,为了避免各种开发人员使用的C语言语法的差异,美国国家标准局为C语言设置了一套完整的国际标准语法,称为ANSI C标准.
[嵌入式牛鼻] C语言,嵌入式系统编程,屏幕操作中的注意事项
[嵌入式问题] C语言在嵌入式系统编程中的注意事项
【牛的文字】
C语言嵌入式系统的屏幕操作编程说明
现在要解决的问题是,嵌入式系统中经常使用的不是一个完整的汉字库,但通常只需要提供有限数量的汉字即可显示必要的显示功能
汉字处理
现在要解决的问题是,嵌入式系统中经常使用的不是一个完整的汉字库,但是通常只需要提供有限数量的汉字即可显示必要的显示功能. 例如,不需要提供在微波炉的LCD上显示“电子邮件”的功能. 不需要在具有中文字符显示功能的空调的LCD上显示“短消息”,依此类推. 但是手机和小灵通通常需要包括一个更完整的汉字库.
如果所包含的汉字库相对完整,则从内部代码计算库中汉字字体的偏移量非常简单: 汉字库按区域位的顺序排列,前一个字节是汉字的区号,下一个字节是单词的位数. 每个区域记录94个汉字c c 嵌入式系统编程,位数是该字符在该区域中的位置. 因此,用于计算汉字在汉字库中的特定位置的公式为: 94 *(区号-1)+位数-1. 负1是因为数组以0开头,而区号位数为1开头. 只需乘以汉字字体占用的字节数即可,即: (94 *(区号-1)+位号-1 )*一种汉字字体占用字节数,以16 * 16点阵字体为例,计算公式为: (94 *(区号-1)+(位号-1))* 32. 汉字库中从该位置开始的32字节信息记录了单词的字体信息.
对于包含更完整的汉字库的系统,我们可以根据上述规则计算字体的位置. 但是,如果只提供几个汉字怎么办?例如几十到几百?最佳做法是:
定义宏:
#define EX_FONT_CHAR()
#define EX_FONT_UNICODE_VAL()(),
#define EX_FONT_ANSI_VAL()(),
定义结构:
typedef struct _wide_unicode_font16x16
{
WORD; / *内部代码* /
BYTE数据[32]; / *字形* /
} Unicode;
#define CHINESE_CHAR_NUM…/ *汉字数* /
用于存储字体的数组:
Unicode中文[CHINESE_CHAR_NUM] =
{
{
EX_FONT_CHAR(“是”)
EX_FONT_UNICODE_VAL(0x4e1a)
{0x04、0x40、0x04、0x40、0x04、0x40、0x04、0x44、0x44、0x46、0x24、0x4c,0x24、0x48、0x14、0x50、0x1c,0x50、0x14、0x60、0x04、0x40、0x40、0x04 ,0x04、0x44、0xff,0xfe,0x00、0x00、0x00、0x00}
},
{
EX_FONT_CHAR(“中”)
EX_FONT_UNICODE_VAL(0x4e2d)
{0x01、0x00、0x01、0x00、0x21、0x08、0x3f,0xfc,0x21、0x08、0x21、0x08、0x21、0x08、0x21、0x08、0x21、0x08,
0x3f,0xf8、0x21、0x08、0x01、0x00、0x01、0x00、0x01、0x00、0x01、0x00、0x01、0x00}
},
{
EX_FONT_CHAR(“云”)
EX_FONT_UNICODE_VAL(0x4e91)
{0x00、0x00、0x00、0x30、0x3f,0xf8、0x00、0x00、0x00、0x00、0x00、0x0c,0xff,0xfe,0x03、0x00、0x07、0x00,
0x06、0x40、0x0c,0x20、0x18、0x10、0x31、0xf8、0x7f,0x0c,0x20、0x08、0x00、0x00}

}c c 嵌入式系统编程,
{
EX_FONT_CHAR(“件”)
EX_FONT_UNICODE_VAL(0x4ef6)
{0x10、0x40、0x1a,0x40、0x13、0x40、0x32、0x40、0x23、0xfc,0x64、0x40、0xa4、0x40、0x28、0x40、0x2f,0xfe,
0x20、0x40、0x20、0x40、0x20、0x40、0x20、0x40、0x20、0x40、0x20、0x40、0x20、0x40}
}
}
要显示特定的汉字,只要与所需的汉字内部代码相同,只需从数组中查找内部代码即可获取字体. 如果先前的汉字按内部代码大小的顺序排列在数组中,则可以使用二进制字体搜索方法更有效地查找汉字的字体.
这是组织小型汉字库的一种非常有效的方法,可以确保程序具有良好的结构.
系统时间显示
可以从NVRAM读取系统时间. 系统通常使用NVRAM生成的第二个中断每秒读取当前时间并将其显示在LCD上. 关于时间的显示,存在效率问题. 因为时间有其特殊性,也就是说,在60秒内只有一分钟的变化,而在60分钟内只有一小时的变化. 如果每次都完全刷新屏幕上的读取时间,则会浪费很多系统.
更好的方法是将小时,分钟和秒存储在时间显示功能的静态变量中,并仅在内容更改时更新显示.
外部无效的DisplayTime(...)
{
静态BYTE byHour,byMinute,bySecond;
BYTE byNewHour,byNewMinute,byNewSecond;
byNewHour = GetSysHour();
byNewMinute = GetSysMinute();
byNewSecond = GetSysSecond();
如果(byNewHour!= byHour)
{
…/ *显示时间* /
byHour = byNewHour;
}
如果(byNewMinute!= byMinute)
{
…/ *显示分钟* /
byMinute = byNewMinute;
}
if(byNewSecond!= bySecond)
{
…/ *显示秒数* /
bySecond = byNewSecond;
}
}
该示例也可以用作C语言中static关键字功能强大的证明. 当然,在C ++语言中,static具有更强大的功能. 它使某些数据和功能与“对象”分开,并成为“类”的一部分. 正是它的这一特性为软件做出了无数出色的设计.
显示
没关系,也没关系,静态图片会走很多路,成为. 随着时间的流逝,在屏幕上显示不同的静止图片是的本质. 因此,要在嵌入式系统的LCD上显示,必须使用计时器. 没有硬件或软件计时器的世界是无法想象的:
(1)没有计时器,操作系统将无法旋转时间片,因此无法进行多任务调度,因此它将不再是多任务操作系统;
(2)没有计时器,多媒体播放软件将无法工作,因为它不知道何时切换到下一帧;
(3)没有计时器,网络协议将无法工作,因为它无法知道数据包传输何时超时并重新传输,并且无法在特定时间完成特定任务.
那么,没有计时器就意味着没有操作系统,网络,多媒体,天将黑吗?因此,合理而灵活地使用各种计时器是软件人员的最基本要求!
在以80186为主要芯片的嵌入式系统中,我们需要使用硬件定时器的中断作为软件定时器,以在发生中断后更改屏幕的显示内容. 在时间显示“ xx: xx”中,让冒号交替显示. 每隔一秒钟中断一次,您需要致电ShowDot:
void ShowDot()

{
静态BOOL bShowDot = TRUE; / *再次欣赏静态关键字的力量* /
如果(bShowDot)
{
showChar(’: ’,xPos,yPos);
}
其他
{
showChar(’’,xPos,yPos);
}
bShowDot =! bShowDot;
}
菜单操作
无数的人类问题终于来临. 在本节中,我们将看到即使在C语言中使用了一些面向对象的思想,如何也将改善软件结构!
需要使用键盘上的“←→”键切换菜单焦点. 当用户在某个菜单中时,如果用户单击键盘上的OK(确定)和CANCEL(取消)键,则会调用焦点菜单的相应处理功能. 我曾经很愚蠢地这样做:
/ *按确定按钮* /
void onOkKey()
{
/ *确定焦点菜单,按确定键,然后调用相应的处理功能* /
切换(当前焦点)
{
案例MENU1:
menu1OnOk();
休息;
菜单2:
menu2OnOk();
休息;
...
}
}
/ *按取消按钮* /
void onCancelKey()
{
/ *确定您在哪个焦点菜单上按了[取消]键并调用相应的处理功能* /
切换(当前焦点)
{
案例MENU1:
menu1OnCancel();
休息;
菜单2:
menu2OnCancel();
休息;
...
}
}

最后一天,我做到了:
/ *“一起封装”菜单的属性和操作* /
typedef struct tagSysMenu
{
char *文字; / *菜单文本* /
BYTE xPos; / * LCD上菜单的x坐标* /
BYTE yPos; / * LCD上菜单的Y坐标* /
void(* onOkFun)(); / *按菜单上的确定键的处理功能指针* /
void(* onCancelFun)(); / *用于按此菜单上的取消键的处理功能指针* /
} SysMenu,* LPSysMenu;
当我定义菜单时,我只需要这样:
静态SysMenu菜单[MENU_NUM] =
{
{
“菜单1”,0、48,menu1OnOk,menu1OnCancel
}
,
{
“菜单2”,7、48,menu2OnOk,menu2OnCancel
}
,
{
“ menu3”,7、48,menu3OnOk,menu3OnCancel
}
,
{
“ menu4”,7、48,menu4OnOk,menu4OnCancel
}
...
};
确定键和取消键的处理变为:
/ *按确定按钮* /
void onOkKey()
{
菜单[currentFocusMenu] .onOkFun();
}
/ *按取消按钮* /
void onCancelKey()
{
菜单[currentFocusMenu] .onCancelFun();
}
该程序已大大简化,并且已经开始非常可扩展!我们仅使用了面向对象的包装思想来使程序结构清晰. 结果是几乎可以在不修改程序的情况下将更多菜单添加到系统中,并且系统的关键处理功能保持不变.
面向对象,真正的上帝!
模拟MessageBox函数
MessageBox函数是Windows编程中的超强材料,我不知道初学者第一次使用了多少个函数. 还记得我们第一次使用MessageBox输出“ Hello,World!”. Windows的第一次对话框?无法计算这个世界上有多少程序员从MessageBox学习Windows编程(“ Hello,World!”,...). 在我的本科学校里,有一个广泛的词汇表,叫做“'Hello,世界'水平的程序员”,意思是入门级的程序员,但是“'Hello,世界'水平”似乎更有趣和生动.

嵌入式系统中没有提供MessageBox,但是鉴于其强大的功能,我们需要对其进行仿真. 一个模拟的MessageBox函数是:
/ **********************************************
/ *函数名称: MessageBox
/ *功能描述: 弹出对话框显示提醒用户的信息
/ *参数说明: lpStr ---字符串输出信息,提醒用户
/ * TYPE ---输出格式(ID_OK = 0,ID_OKCANCEL = 1)
/ *返回值: 返回对话框收到的键值,只有KEY_OK,KEY_CANCEL两种
/ **********************************************
typedef枚举TYPE {ID_OK,ID_OKCANCEL} MSG_TYPE;
外部字节消息框(LPBYTE lpStr,字节类型)
{
BYTE键= -1;
ClearScreen(); / *清除屏幕* /
DisplayString(xPos,yPos,lpStr,TRUE); / *显示字符串* /
/ *根据对话框的类型,确定是否显示确定并取消* /
开关(TYPE)
{
案例ID_OK:
DisplayString(13,yPos +高+ 1,“确定”,0);
休息;
案例ID_OKCANCEL:
DisplayString(8,yPos + High + 1,“ OK”,0);
DisplayString(17,yPos +高+ 1,“取消”,0);
休息;
默认值:
休息;
}
DrawRect(0,0,239,yPos +高+ 16 + 4); / *并条机* /
/ * MessageBox是一个模式对话框,阻止操作,等待按钮* /
同时(((key!= KEY_OK)||(key!= KEY_CANCEL))
{
key = getSysKey();
}
/ *返回键类型* /
如果(键== KEY_OK)
{
返回ID_OK;
}
其他
{
返回ID_CANCEL;
}
}
以上功能与我们通常在VC ++等中使用的MessageBox有何相似之处?实施此功能,您将看到它在嵌入式系统中的神奇应用.
摘要
本文是本系列文章中最熟练的. 它为嵌入式系统的屏幕显示提供了一些非常巧妙的处理方法. 灵活使用它们,我们再也不会因为LCD上混乱的显示内容而分心.
屏幕是嵌入式系统生存的重要辅助工具. 可恶的显示将使用户逃跑. 如果屏幕编程处理不当,它将成为该软件中系统性和混乱性最低的部分,而作者为此蒙受了极大的痛苦.
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-228870-1.html
另一舰打开火控
北洋舰队号称亚洲第一
而且癌症这个东西你越怕它
今年30一公斤