单片机可移植程序书写习惯
- 格式:doc
- 大小:29.00 KB
- 文档页数:2
单片机编程语言介绍单片机(Microcontroller,简称MCU)是一种完整的计算机系统,由中央处理器(CPU)、内存、输入输出引脚和一些外设集成在一块芯片上。
它广泛应用于嵌入式系统中,控制各种电子设备。
而单片机编程语言则是用来编写单片机程序的语言,常见的单片机编程语言包括汇编语言、C语言以及基于C语言改进的高级语言等。
I. 汇编语言汇编语言是一种底层的编程语言,直接使用机器指令来编写程序。
在汇编语言中,每条指令被映射到特定的机器码,通过对寄存器和内存进行操作,实现对硬件的控制。
汇编语言的编写相对繁琐和复杂,需要对硬件细节有深入的了解。
汇编语言具有较高的灵活性和效率,可直接对硬件进行操作,对于一些对性能要求较高且对程序大小要求较小的应用场景较为适用。
然而,由于其复杂性和可读性较差,编写和维护汇编语言程序相对困难,且对开发人员的技术要求较高。
II. C语言C语言是一种高级的编程语言,被广泛应用于单片机编程中。
相比于汇编语言,C语言更易于学习和使用,具有更好的可读性和可移植性。
C语言不需要直接接触机器码,而是通过编译器将代码转换为机器码。
C语言具有丰富的库函数和语法特性,能够方便地实现各种功能。
它提供了丰富的结构和数据类型,如条件语句、循环语句、函数等,使得编写和调试程序更加便捷。
C语言在单片机编程中得到广泛应用,特别适合中小型项目和对开发周期要求较短的应用。
III. 基于C语言的高级语言除了C语言,还有一些基于C语言改进的高级语言,如C++、C#、Python等,也可以用于单片机编程。
这些高级语言相比于C语言,提供了更多的面向对象编程(OOP)特性和库函数,使得开发更加高效和便捷。
C++是一种扩展自C语言的面向对象编程语言,通过封装、继承和多态等特性,使程序具有更好的可维护性和扩展性。
C#则是微软推出的面向对象编程语言,提供了强大的框架和库,可用于开发Windows平台的应用。
而Python则以其简洁、灵活和易读的代码著称,适合于快速原型开发和开发周期较短的项目。
单片机的编程技巧简介:单片机是一种微型计算机系统,具有集中控制和处理能力。
在现代电子设备中,单片机的应用非常广泛。
本文将讨论一些单片机编程的技巧,以帮助读者更好地应对单片机编程的挑战。
一、充分了解单片机的指令集在单片机编程中,了解单片机的指令集是非常重要的。
每个单片机都有自己的指令集,这些指令用于执行各种操作,比如读取、写入、计算等。
通过充分了解指令集,开发人员可以更好地利用单片机的功能,提高程序的效率。
二、合理设计程序结构在编写单片机程序时,合理的程序结构设计可以提高程序的可读性和维护性。
可以将程序分为多个模块,每个模块实现一个特定的功能。
同时,通过良好的命名规范和注释,可以帮助其他开发人员更好地理解和调试程序。
三、合理利用中断中断是单片机编程中的重要机制,可以响应外部事件并及时处理。
在设计程序时,合理利用中断可以提高程序的响应能力和实时性。
比如,可以使用定时中断来进行周期性任务的处理,或者使用外部中断来响应外部设备的输入。
四、合理选择数据类型和变量在编写单片机程序时,合理选择数据类型和变量可以提高程序的效率和资源利用率。
对于需要高精度计算的任务,可以选择浮点型数据类型;对于需要节约内存的任务,可以选择整型或枚举类型。
五、注意优化程序代码在单片机编程中,代码的优化可以提高程序的执行效率和响应速度。
可以通过减少不必要的计算、精简程序代码、消除冗余操作等方式进行优化。
同时,合理选择编译器和编译选项也可以提高代码的优化效果。
六、合理利用调试工具调试是单片机编程中不可或缺的一环。
合理利用调试工具可以帮助开发人员快速定位和修复程序中的错误。
可以使用仿真器、调试器等工具进行单步调试,以观察程序的执行情况并进行错误排查。
七、不断提升学习和实践单片机编程是一个不断学习和实践的过程。
通过不断学习单片机的相关知识和技术,积极参与实际项目的开发,可以不断提升自己的单片机编程技巧。
同时,了解单片机市场的最新动态和发展趋势,也有助于指导自己的学习和实践。
单⽚机编程语⾔的⽐较引⾔单⽚机⼜称单⽚微控制器,它是把⼀个计算机系统,包括cpu、ram、rom、定时/计数器和多种i/o接⼝集成到⼀个芯⽚上。
由于单⽚机的种种优点和特性,其应⽤领域极其⼴泛。
单⽚机系统同样也由硬件系统和软件系统构成,因此涉及到程序的编写问题。
单⽚机的编程语⾔很多,⼤致分成三类:机器语⾔、汇编语⾔、⾼级语⾔。
机器语⾔由于繁琐容易出错,⼀般⽤户已经不再使⽤。
下⾯分别对汇编语⾔和最常⽤的⾼级语⾔进⾏分析。
单⽚机的汇编语⾔汇编语⾔是⼀种⽤⽂字助记符来表⽰机器指令的符号语⾔,是最接近机器码的⼀种语⾔。
其主要优点是占⽤资源少,程序执⾏效率⾼,由于它⼀条指令就对应⼀条机器码,每⼀步的执⾏动作都很清楚,并且程序⼤⼩和堆栈调⽤情况都容易控制,调试起来也⽐较⽅便。
但是不同的类型的单⽚机,其汇编语⾔可能有点差异,所以不易移植,因为他们的指令系统是有区别的。
但懂得汇编语⾔可帮助了解影响任何语⾔效率的特殊规定。
例如,懂得汇编语⾔指令就可以使⽤在⽚内ram作变量的优势,因为⽚外变量需要⼏条指令才能设置累加器和数据指针进⾏存取。
同样的,当要求使⽤浮点数和启⽤函数时也只有具备汇编编程经验才能避免⽣成庞⼤的、效率低的程序,对于这⽅⾯的编程,没有汇编语⾔是做不到的。
单⽚机的c语⾔单⽚机的c语⾔是⼀种编译型程序设计语⾔,它兼顾了多种⾼级语⾔的特点,并具备汇编语⾔的功能。
c语⾔具有功能丰富的库函数,运算速度快,编译效率⾼,有良好的可移植性,⽽且可以实现直接对系统硬件的控制。
此外,c语⾔程序具有完整的程序模块结构,从⽽为软件开发中采⽤模块化程序设计⽅法提供了有⼒的保障。
与汇编相⽐,有如下优点:对单⽚机的指令系统不要求了解,仅要求对51的存储器结构有初步了解,⾄于寄存器分配、不同存储器的寻址及数据类型等细节均由编译器管理。
程序有规范的结构,可分为不同的函数。
这种⽅式可使程序结构化,将可变的选择与特殊操作组合在⼀起,改善了程序的可读性。
单片机模块化编程的原则有哪些目前我们在学习和开发单片机时广泛采用c 语言进行编程,当我们开发的单片机项目较小时,或者我们所写的练习程序很小时,我们总是习惯于将所有代码编写在同一个c 文件下,由于程序代码量较少,通常为几十行或者上百行,此时这种操作是可行方便的,也没有什么问题。
但如果要开发的项目较大,代码量上千行或者上万行甚至更大,如果你还继续将所有代码全部编写在仅有的一个 c 文件下,这种方式的弊病会凸显出来,它会给代码调试、更改及后期维护都会带来极大的不便。
试想一下,当你尝试着从几千几万行代码中定位到某一位置或者去寻找某一错误点,上下拉动巨长的滚动条慢慢地、一点点地浏览整个 c 文件,是件多么令人眼花缭乱,头昏脑胀的事。
模块化编程可解决这个问题,我们只要根据实际需要使用模块化编程的思维将具有不同功能的程序封装在不同模块中,将各个不同模块存放在不同的 c 文件中。
模块化编程后的程序不但使整体的程序功能结构清晰明了,同时也提高程序代码的利用率,有些模块代码我们可以直接进行移植或者经简单修改就可另作他用,好比封装好的函数。
那么什么是模块化呢?首先我们来简单来聊聊模块概念,我们可能听说过电源模块,通信模块,这些是硬件模块,它们都提供一些接口,譬如电源模块会有输出额定电压电流的接口,通信模块可能提供了RS232、USB等接口。
那么对软件来说模块是怎样的呢?软件里的模块跟硬件模块类似,抽象地说就像一个黑盒子,盒子内部细节我们可以不予理会,我们只关心盒子给我们提供什么东西,即提供了什么接口,利用这些接口我们能实现什么功能。
我们把相对独立,具有独立功能用代码编写在一个 c 文件下,把需要对外的函数或变量进行声明供外部使用,把不需要的细节尽可能对外部屏蔽起来,这就是软件模块化编程的思维。
这样不同的模块占用不同c 文件,一个个c 文件将整个项目串接起来实现所有的功能。
1. 模块化编程的原则:模块化编程通常要遵循以下几个原则:。
移植心得张涛UC/OS-II内核可以分为与处理器无关的代码,与处理器相关的代码以及与应用相关的代码3个部分。
移植中只需修改与处理器相关部分和应用相关的代码的文件,即包括:处理器相关C文件OS_CPU.H,OS_CPU_C.C,汇编文件OS_CPU_ASM.ASM和配置文件OS_CFG.H,其它代码几乎不需要改变。
一.改写最简单的OS_CPU.H主要声明四个宏:1.数据类型的设定:注意BOOLEAN要定义成unsigned char 类型,因为bit类型为C51特有,不能用在结构体里.2.堆栈的增长方向:MCS-51堆栈从下往上增长(1=向下,0=向上),OS_STK_GROWTH定义为0。
3.定义临界段:EA=0关中断;EA=1开中断.这样定义即减少了程序行数,又避免了退出临界区后关中断造成的死机.4.定义任务切换宏;#define OS_TASK_SW() OSCtxSw() 因为MCS-51没有软中断指令,所以用程序调用代替。
两者的堆栈格式相同,RETI指令复位中断系统,RET则没有。
实践表明,对于MCS-51,用子程序调用入栈,用中断返回指令RETI出栈是没有问题的,反之中断入栈RET出栈则不行。
总之,对于入栈,子程序调用与中断调用效果是一样的,可以混用。
在没有中断发生的情况下复位中断系统也不会影响系统正常运行。
二.修改OS_CPU_C.C文件1.初始化系统时钟:操作系统tick时钟我使用了51单片机的T0定时器,它的初始化代码可参考任哲书上关于时钟初始化的文件2.编写10个与操作体系有关的钩子函数3.修改任务堆栈初始化函数OSTaskStkInit()。
uC/OS-II 中每个任务都有自己的堆栈空间,并且必须声明为OS_STK类型,主要完成对用户任务的堆栈进行初始化。
OSTaskStkInit函数总是返回用户栈最低地址。
4. 最后还有几点必须注意的事项.本来原则上我们不用修改与处理器无关的代码,但是由于KEIL编译器的特殊性,这些代码仍要多处改动.因为KEIL缺省情况下编译的代码不可重入,而多任务系统要求并发操作导致重入,所以要在每个C函数及其声明后标注reentrant 关键字.另外,"pdata","data"在uCOS中用做一些函数的形参,但它同时又是KEIL的关键字,会导致编译错误,我通过把"pdata"改成"ppdata","data"改成"ddata"解决了此问题。
单片机拖拽编程摘要:1.单片机拖拽编程简介2.单片机拖拽编程的原理3.单片机拖拽编程的优势4.单片机拖拽编程的应用领域5.单片机拖拽编程的发展趋势和挑战正文:单片机拖拽编程是一种新型的编程方式,它通过可视化的界面,让开发者能够像拖拽组件一样,轻松地编写单片机的程序。
这种编程方式大大降低了单片机编程的难度,同时也提高了编程的效率。
单片机拖拽编程的原理是,通过将单片机的指令和功能模块化,形成一个个可供拖拽的组件。
开发者只需要通过拖拽这些组件,就能完成程序的编写。
这些组件可以包括基本的输入输出模块、数据处理模块、通信模块等。
当组件被拖拽到程序框图中后,系统会自动生成对应的程序代码。
单片机拖拽编程的优势主要体现在两个方面。
首先,它大大降低了编程的难度。
拖拽编程的方式使得编程变得更加直观,开发者不需要深入了解底层的硬件原理,也能完成程序的编写。
其次,它极大地提高了编程的效率。
传统的编程方式需要手动编写每一行代码,而拖拽编程则可以自动生成代码,大大节省了编程的时间。
单片机拖拽编程的应用领域非常广泛。
从工业控制到智能家居,从医疗设备到消费电子产品,都可以看到单片机拖拽编程的应用。
通过拖拽编程,开发者可以更加专注于功能的实现,而不用担心复杂的编程问题。
然而,单片机拖拽编程也面临一些挑战。
首先,由于单片机的种类繁多,要实现拖拽编程,就需要对每一种单片机都进行深入的了解。
其次,拖拽编程的普及,需要开发一个通用的平台,这也是一个巨大的挑战。
总的来说,单片机拖拽编程是一种非常有前景的编程方式。
它不仅降低了编程的难度,提高了编程的效率,而且拓宽了编程的应用领域。
单片机汇编程序编码规范 - 单片机软件设计更多地是一种工程,而不是一种个人艺术。
假如不统一编程规范,最终写出的程序,其可读性将较差,这不仅给代码的理解带来障碍,增加维护阶段的工作量,同时不规范的代码隐含错误的可能性也比较大。
分析表明,编码阶段产生的错误当中,语法错误或许占20%左右,而由于未严格检查软件规律导致的错误、函数(模块)之间接口错误及由于代码可理解度低导致优化维护阶段对代码的错误修改引起的错误则占了一半以上。
可见,提高软件质量必需降低编码阶段的错误率。
如何有效降低编码阶段的错误呢?这需要制定具体的软件编程规范,并培训每一位程序员,最终的结果可以把编码阶段的错误降至10%左右,同时也降低了程序的测试费用,效果相当显著。
本文从代码的可维护性(可读性、可理解性、可修改性)、代码规律与效率、函数(模块)接口、可测试性四个方面阐述了软件编程规范,规范分成规章和建议两种,其中规章部分为强制执行项目,而建议部分则不作强制,可依据习惯取舍。
1.排版规章1程序块使用缩进方式,函数和标号使用空格缩进,程序段混合使用TAB和空格缩进。
缩进的目的是使程序结构清楚,便于阅读和理解。
默认宽度应为8个空格,由于Word中为4个空格,为示范清楚,此处用2个代替(下同)。
例如:MOV R1, #00HMOV R2, #00HMOV PMR, #PMRNORMALMOV DPS, #FLAGDPTRMOV DPTR, #ADDREEPROMread1kloop:read1kpage:INC R1MOVX A, @DPTRMOV SBUF, AJNB TI, $CLR TIINC DPTRCJNE R1, #20H, read1kpageINC R2MOV R1, #00HCPL WDICJNE R2, #20H, read1kloop ;END OF EEPROM规章2在指令的操作数之间的,使用空格进行间隔,接受这种松散方式编写代码的目的是使代码更加清楚。
单片机模块化编程的好处与技巧
单片机模块化编程是指将大型程序分解为多个小的、相对独立的模块,每个模块都有自己的功能,通过组合这些模块来实现整个程序的功能。
单片机模块化编程的好处与技巧如下:
好处:
1. 提高程序可读性
将一个大的程序分解为多个小的模块,每个模块都有自己的功能,这样可以使程序结构清晰,易于理解和维护。
2. 降低程序开发难度
单片机模块化编程可以降低程序的复杂度,减少代码的冗余,提高开发效率。
3. 提高程序可扩展性
采用模块化编程的方式可以使程序易于扩展,只需添加新的模块,就可以实现新的功能,而不需要对整个程序进行重构。
4. 提高代码复用性
采用模块化编程的方式可以使得代码复用性更高,一些重复的代码可以封装成模块,减少代码冗余。
技巧:
1. 模块功能单一
每个模块应该只实现一个明确的功能,不要将多个功能集成在一个模块中,这样可以使模块更加清晰。
2. 模块间接口清晰
模块之间的接口应该清晰,包括输入输出参数、返回值类型、异常处理等,以便于其他模块调用和维护。
3. 模块独立性高
每个模块应该尽可能地独立,不要依赖于其他模块的实现细节,以便于其他模块调用和维护。
4. 模块可重用性高
每个模块应该尽可能地可重用,不要将模块写得太具体,以便于其他模块调用和复用。
5. 模块测试完善
模块开发完成后,应该进行充分的测试,确保模块的功能正确性和稳定性,以便于后续的整体集成测试。
单片机可移植程序的一些小习惯
对于一些状态的集合,尽可能使用enum而不是#define 来定义。
如:
enum {OFF = 0, ON = 1};
远比定义成下面这样好一些:
#define OFF (0) #define ON (1)
两种写法编译的效果是一样的,但是写程序及看程序的人员来说感觉就不一样了。
用enum定义时,可以觉得OFF与ON是一个集合,有相关性(且可减少程序中#define的定义)。
但用#define定义时,完全可认为OFF与ON不相干。
特别是在程序中#define定义过多时,查找并理解它的意思都是一个痛苦。
(如:uc/os,看见它的一大堆#define都头大,要完全明白那一堆定义都得花不少时间)。
第二,程序中少用下面这种预编译命令,不符合条件的程序段是不被编译的,都不检查语法错误,当在某些情况下打开了条件开关时,也许一堆错误就出现了。
而且程序并不利于阅读,当读程序时突然得去查找某东东是否#define真是痛苦。
当然为了程序的通用性,一定要用,那么一定要记住好好测试一下。
#if
... #ifdef
...
再说一下其它的习惯:
1、I/O口输出电平定义一下,以后万一I/O电平驱动取反,一改就好。
// I/O Port Stutes
enum {OFF = 0, ON = 1};
// Led Stutes
enum {LED_ON = 0, LED_OFF = 1};
eg. LED = LED _ON; // 低电平驱动LED亮。
2、I/O口与任何的其它IC接口,I/O口都要定义,不能直接使用I/O口。
(方便以后用于其它的应用中whn)如93C46:
#define CS93C46 P1_0 // 片选信号
#define SK93C46 P1_1 // 时钟信号
#define DI93C46 P1_2 // 数据输入,相对93C46而言 (即93C46的数据输入)
#define DO93C46 P1_3 // 数据输出
如字符型LCD:
#define LCD_PORT P0 // lcd数据口
#define LCD_RS P1_7 // 数据指令选择。
低--ins ; 高--data
#define LCD_RW P1_6 // 读写选择。
低--w ; 高--r
#define LCD_EN P1_5 // 使能。
高到低--使能。
3、键盘口要定义输入口及屏蔽字,如:
#define KEYMASK 0x0f
#define KEYPORT P2
4、串口用中断驱动,要带Buf。
5、取按键的程序及串口的程序编2个,一个为非阻塞式,一个为阻塞式(不按键或不收到数据不返回)。
6、晶振频率要定义
#define FOSC 11059200ul // 频率
7、波特率定义
#define BAUD (4800) // 波特率4800
#define SMODX (0) // 是否倍频 0-NO or 1-YES #define T1H_VAL (256 - (UINT8)(FOSC * (1<1.0 / 384 / BAUD)) #define T1L_VAL T1H_VAL
8、延时程序赋值时写成FOSC函数,编译器会预先算,不占用MCU资源以后移植方便
9、液晶程序一定要定义长宽
如点阵型:
#define ROW (64)
#define CLUM (128) // 128*64
字符型:
#define ROW (4)
#define CLUM (20)
#define ROW1_ADDR (0x80 + 0) // 第一行地址
#define ROW2_ADDR (ROW1_ADDR + 0x40) // 第二行地址
#define ROW3_ADDR (ROW1_ADDR + CLUM) // 第三行地址
#define ROW4_ADDR (ROW2_ADDR + CLUM) // 第四行地址
然后所有的和液晶地址有关的计算全部引用这2个量。
换用任何屏直接一改,高层不变。
10、驱动层与应用接口层分在不同的文件,移植方便。
如:键盘、LCD、串口等。