嵌入式系统编程中C语言的注意事项(3)

电脑杂谈  发布时间:2020-05-31 13:19:44  来源:网络整理

c嵌入脚本解释器_c c 嵌入式系统编程_高质量c /c编程指南

姓名: 徐娇: 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编程指南_c c 嵌入式系统编程_c嵌入脚本解释器

}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()

c嵌入脚本解释器_高质量c /c编程指南_c c 嵌入式系统编程

{

静态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();

休息;

...

}

}

高质量c /c编程指南_c c 嵌入式系统编程_c嵌入脚本解释器

最后一天,我做到了:

/ *“一起封装”菜单的属性和操作* /

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,世界'水平”似乎更有趣和生动.

c嵌入脚本解释器_高质量c /c编程指南_c c 嵌入式系统编程

嵌入式系统中没有提供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

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...