教你如何用C++写单片机程序

教你如何用C++写单片机程序
教你如何用C++写单片机程序

教你如何用C++写单片机程序

关键词:C++ 面向对象单片机

从大一就开始学习单片机,学51,A VR编程都使用C语言的风格,即面向过程,只要能画出程序流程图,程序基本就born了。我热衷于编程,尤其是C++,当时想有没有一天,C++的类和对象也能出现在单片机中?

历经世事沧桑,事到如今,我终于有机会,和大家一起学习使用真正面向对象的C++来控制单片机。目前单片机编译器大部分只支持C语言,C++还不够普及,但我们有理由相信,有着更先进的面向对象的理念,有更加平易近人的类和继承,C++必将取代C,成为单片机程序的主流。试看将来环球单片机,必是C++的世界!

下面大家跟着我来一起学习怎么用C++给单片机编程序!本文要求大家玩过A VR单片机,有过C语言编程经验,而且要对VC6.0开发环境有一定了解。

必备软件:VC6.0(用于编辑源程序),WinA VR(用于生成Makefile,支持A VR系列单片机),Proteus(用于仿真调试)。

首先,你的电脑上要装有VC6.0,进入后选菜单【file】---【new】新建工程,如图1选择Makefile工程,输入工程名称,路径,点确定。

图1_新建工程

一路OK建好工程,界面如图2。这个工程是专门写makefile脚本的,你如果学A VR单片机使用avr-gcc那应该对makefile有一定了解,如果想多了解一点详见https://www.360docs.net/doc/4f13184462.html,/view/974566.html?wtp=tt(呵呵,百度百科)。

你还需要安装WINA VR,这是个免费软件,网上很多资源,这个软件很容易安装,一路Next 就可以啦!为了使用方便,我的WINAVR安装到了C盘根目录下的WINA VR文件夹。安装好后,可以直接用它来编辑源代码,今天我就不讲它的使用方法了,只讲怎么生成makefile。自我感觉用熟悉的VC6.0环境编写程序心情很愉快,大家还是跟我一起来,打造

舒服的编辑环境!建好工程编译成功的界面如图2所示。

图2_工程界面

建好的工程里可以写C++代码了,下面是我要以图3的电路图写一个控制LED亮灭的程序。这个用C很easy,是吧?用Proteus仿真大家应该都会我就不罗嗦了,效果可以看本期附带的视频。

图3_电路图

在工程界面中,点【file】---【new】,选“C++ Source File”,如图4所示,在file一栏中输main点OK,注意一定是main,不要写错,一会就知道为什么了。然后进入编辑页面,我们就可以用C++编写源代码了,呵呵,程序如下,是个非常简单的类LED,短短几行程序展现了一个全新的面貌:没有了C语言的那些函数堆,取而代之的是高效美观的类和对象。

图4_新建文件

源代码:

#include

class LED

{

public:

LED()

{

DDRB|=0x01;

PORTB&=~0x01;

}

~LED()

{

DDRB&=~0x01;

PORTB&=~0x01;

}

void LEDon(void)

{

PORTB&=~0x01;

}

void LEDoff(void)

{

PORTB|=0x01;

}

void LEDdelay(void)

{

unsigned int a,b;

for(a=10000;a;a--)

for(b=3000;b;b--);

}

};

int main(void)

{

LED led1;

while(1)

{

led1.LEDoff();

led1.LEDdelay();

led1.LEDon();

led1.LEDdelay();

}

}

编写完后,还需要对工程进行一些配置,大家要沉着冷静,跟我一步一步走,不要贪图路旁的景色。打开菜单【Project】-- 【Settings】,在“Build Command Line”中填入“make”,OK,如图5所示。

图5_ProjectSettings

然后打开菜单【Tools】- 【Options】,选“Derectories”标签页,在下拉菜单“Show Directories For”选“Executable Files”,将Winavr的可执行程序路径添加到VC6.0中,这里需要两条:winavr安装路径\bin 和winavr安装路径\utils\bin就行啦,如图6所示。

图6_ToolsOptions

马上就要成功了,但还有最关键的一项没做,就是写一个makefile。这里我们就用winavr 自带的工具mfile来完成。从开始菜单找到winavr,一个个找,看到mfile,单击打开,界面如图7所示。

将它保存到工程文件夹下,慢慢修改。有很多选项需要改,大家也不必全都搞懂,一般直接用现成的就行,我就是一直用我一开始生成好的makefile,一劳永逸,使用时要遵守规则就

行了,比如,我们工程里的源程序文件名为main,这是为了让Makefile认出来,以便进行编译。如果改成别的名字,Makefile就会找不到主文件而报错。如果你想用别的名字,也可以,在Makefile里找到一行:

# Target file name (without extension).

TARGET = main

将“TARGET=”后面改成你的文件名(不要加后缀)就可以了。

后面不远处有如下几行

# List C source files here. (C dependencies are automatically generated.)

SRC =

# List C++ source files here. (C dependencies are automatically generated.)

CPPSRC = $(TARGET).cpp

这就把源代码加入了Makefile的识别文件里,之后就可以对其进行编译、链接了。

还有一个选项是选择单片机型号:

# MCU name

MCU = atmega8

你也可以改成其他型号,如atmega16,atmega128等等。

还有一个选项选择编译器:

CC = avr-gcc

我们要用C++编译器,改成

CC = avr-g++

就行啦!

建议大家自己学习一下这些选项,我附带的资料中makefile大家也可以直接拿来用。

完成上述这些,我们该松口气了吧?

在VC6.0中,习惯性地按F7,激动人心的时刻到了,0 errors,0 warnings.!!!多么熟悉的面孔!祝贺你,已经成功编写了第一个C++源程序!其重大意义不亚于我们第一个helloworld 程序!好了,我们烧录到单片机中,用proteus仿真下结果,哈哈一切正常!

如何使用BSL方式给MSP 单片机烧录程序

如何使用BSL方式给MSP430单片机烧录程序 一,使用两个软件:IAR(EW430)和MSP430BSL.exe 二,IAR软件用于编程和编译;BSL软件负责载入烧录。三,在IAR中编程操作: IAR Systems是全球领先的嵌入式系统开发工具和服务的供应商。公司成立于1983年,迄今已有27年,提供的产品和服务涉及到嵌入式系统的设计、开发和测试的每一个阶段,包括:带有C/C++编译器和调试器的集成开发环境(IDE)、实时操作系统和中间件、开发套件、硬件仿真器以及状态机建模工具。 国内普及的MSP430开发软件种内不多,主要有IAR公司的Embedded Workbench for MSP430(简称为EW430)和AQ430。 目前IAR的用户居多。IAR EW430软件提供了工程管理,程序编辑,代码下载,调试等所有功能。并且软件界面和操作方法与IAR EW for ARM等开发软件一致。因此,学会了IAR EW430,就可以很顺利地过渡到另一种新处理器的开发工作。 IAR新建工程步骤 Step1:选择主菜单的File >New>Workspace命令,然后开启一个空白工作区窗口 Step2:选择主菜单Project>Create New Project>选择Empty project。点击OK。最好新建一个文件夹,用于放置所有的生成文件。选择保存路径后,点击保存,新工程建立完毕 Step3:file>new>file>编辑代码>save>文件名可以自己起,但后面一定要加 ”.c” ,保存为C文件 Step4: 右击工程名,将写好的程序添加进去Add>Add Files,也可以用Add>Add“main.c”添加入工程。 Step5: 右击工程名,点击Option>General Options>Device>选择MSP430F149 Step6: 继续设置Linker>Output>文件名.txt(这步很关键)>fomat>

51单片机实验程序

3 3 3 用查表方式编写y=x1 +x2 +x3 。(x 为0~9 的整数) #include void main() { int code a[10]={0,1,8,27,64,125,216,343,512,729}; //将0~9 对应的每位数字的三次方的值存入code中,code为程序存储器,当所存的值在0~255 或-128~+127 之间的话就用char ,而现在的值明显超过这个范围,用int 较合适。int 的范围是0~65535 或-32768~32767 。 int y,x1,x2,x3; //此处定义根据习惯,也可写成char x1,x2,x3 但是变量y 一定要用int 来定义。 x1=2; x2=4; x3=9; //x1,x2,x3 三个的值是自定的,只要是0~9 当中的数值皆可,也可重复。 y=a[x1]+a[x2]+a[x3]; while(1); //单片机的程序不能停,这步就相当于无限循环的指令,循环的内容为空白。 } //结果的查询在Keilvision 软件内部,在仿真界面点击右下角(一般初始位置是右下角)的watch 的框架内双击“double-click or F2 to add”文字输入y 后按回车,右侧会显示其16 进制数值如0x34,鼠标右键该十六进制,选择第一行的decimal,可查看对应的10 进制数。 1、有10 个8 位二进制数据,要求对这些数据进行奇偶校验,凡是满足偶校验的 数据(1 的个数为偶数)都要存到内RAM50H 开始的数据区中。试编写有关程序。 #include void main() { int a[10]={0,1,5,20,24,54,64,88,101,105}; // 将所要处理的值存入RAM 中,这些可以根据个人随意设定,但建议不要超过0~255 的范围。 char i; // 定义一个变量 char *q=0x50; // 定义一个指针*q 指向内部0x50 这个地址。 for(i=9;i>=0;i--) //9~0 循环,共十次,也可以用for(i=0;i<10;i++) { ACC=a[i]; //将a[i] 的值赋给累加器ACC if (P==0) //PSW0 位上的奇偶校验位,如果累加器ACC 内数值1 的个数为偶数那么P 为0,若为奇数,P 为1。这里的P 是大写的。 { *q=a[i]; q++; // 每赋一个值,指针挪一个位置指向下一个。 } } while(1); //同实验一,程序不能停。 }

51单片机考试常见试题简答 题

简答题部分 1、什么叫堆栈? 答:堆栈是在片内RAM中专门开辟出来的一个区域,数据的存取是以"后进先出"的结构方式处理的。实质上,堆栈就是一个按照"后进先出"原则组织的一段内存区域。 2、进位和溢出? 答:两数运算的结果若没有超出字长的表示范围,则由此产生的进位是自然进位;若两数的运算结果超出了字长的表示范围(即结果不合理),则称为溢出。 3、在单片机中,片内ROM的配置有几种形式?各有什么特点? 答:单片机片内程序存储器的配置形式主要有以下几种形式:(1)掩膜(Msak)ROM型单片机:内部具有工厂掩膜编程的ROM,ROM中的程序只能由单片机制造厂家用掩膜工艺固 化,用户不能修改ROM中的程序。掩膜ROM单片机适合于 大批量生产的产品。用户可委托芯片生产厂家采用掩膜方法 将程序制作在芯片的ROM。 (2)EPROM型单片机:内部具有紫外线可擦除电可编程的只读存储器,用户可以自行将程序写入到芯片内部的EPROM 中,也可以将EPROM中的信息全部擦除。擦去信息的芯片 还可以再次写入新的程序,允许反复改写。 (3)无ROM型单片机:内部没有程序存储器,它必须连接程序存储器才能组成完整的应用系统。 无ROM型单片机价格低廉,用户可根据程序的大小来选择外接 程序存储器的容量。这种单片机扩展灵活,但系统结构较复 杂。 (4)E2ROM型单片机:内部具有电可擦除叫可编程的程序存储器,使用更为方便。该类型目前比较常用 (5) OTP(One Time Programmable)ROM单片机:内部具有一次可编程的程序存储器,用户可以在编程器上将程序写入片 内程序存储器中,程序写入后不能再改写。这种芯片的价 格也较低。 4、什么是单片机的机器周期、状态周期、振荡周期和指令周期?它们之间是什么关系? 答:某条指令的执行周期由若干个机器周期(简称M周期)构成,一个机器周期包含6个状态周期(又称时钟周期,简称S周期),而一个状态周期又包含两个振荡周期(P1和P2,简称P周期)。也就是说,指令执行周期有长有短,但一个机器周期恒等于6个状态周期或12个振荡周

C语言程序简单例子讲解学习

实验二参考答案 1.输入两个整型数字,输出他们的和。 #include main() { int a, b, sum; scanf(“%d%d ”, &a, &b); sum=a+b; printf(“a+b=%d ”, sum); } 2.输入两个实型数,输出他们的和与乘积。 #include main() { float a, b, sum, product; scanf(“%f%f ”, &a, &b); sum=a+b; product=a*b; printf(“a+b=%5.2f, a*b =%5.2f ”, sum, product); } 3.求方程02=++c bx ax 的根(设042≥-ac b )(其中a ,b ,c 的值由键盘输入)。 #include #include main() { float a, b, c, dt, x1, x2; scanf(“%f%f%f ”, &a, &b, &c); dt=sqrt(b*b-4*a*c); x1=(-b+dt)/(2*a); x2=(-b-dt)/(2*a); printf(“x1=%5.2f, x2 =%5.2f ”, x1, x2); }

4.鸡兔同笼,已知鸡兔总头数为h,总脚数为f,求鸡兔各多少只?(h和f的值由键盘输入,输出鸡和兔的头数) #include main() { int h, f, x,y; scanf(“%d%d”, &h, &f); x=2*h-f/2; y=f/2-h; printf(“x=%d, y =%d”, x, y); }

单片机如何运行程序

单片机如何运行程序 知道了单片机通过I/O口与外设打交道,也知道了单片机的程序与数据如何保存,到底单片机是如何运行程序的?原来单片机和其他微机一样,也拥有一个中央处理器(CPU),它是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU 负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。它在单片机中的核心地位见图2.10所示。它通过单片机的内部总线,将单片机内部的各个部分:程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等联系在一起,内部总线有三种:数据总线,专门用来传送数据信息,地址总线专门用来传送地址信息,选中各操作单元,控制总线专门用来传送CPU各种控制命令,以便CPU统一指挥协调工作。完成程序所要执行的各种功能。CPU执行程序一般包括两个主要过程:第一,就是从程序存储器中取出指令,指令的地址由PC指针提供,在前面我们已经知道,PC指针在CPU取指后会自动加一,所以PC指针总是指向下一个将要取出的指令代码或操作数。这样,就能保证程序源源不断往下执行。第二,就是执指过程,取出的指令代码首先被送到CPU中控制器中的指令寄存器,再通过指令译码器译码变成各种电信号,从而实现指令的各种功能。 4.怎样保证CPU工作? 现在我们知道了单片机怎样取指、执指,即怎样运行程序了。那么怎样才能保证CPU有序的工作?这就必须提到单片机的两个非常重要的外围电路:单片机的时钟电路和复位电路。在单片机上面有两个引脚,分别是它的第18、19脚,其功能如下。

Pin19:时钟XTAL1脚,片内振荡电路的输入端。 Pin18:时钟XTAL2脚,片内振荡电路的输出端。 89S51的时钟有两种方式,一种是片内时钟振荡方式,但需在18和19脚外接石英晶体和振荡电容,振荡电容的值一般取10p~30p。另外一种是外部时钟方式,即将XTAL1接地,外部时钟信号从XTAL2脚输入。如图2.11 当时钟电路起振后,产生一定频率的时钟信号,单片机的CPU在时钟信号的控制下,就能一步一步完成自己的工作。通常我们必须了解以下几种周期。 【振荡周期】:单片机外接石英晶体振荡器的周期。如外接石英晶体的频率若为12MHz,这其振荡周期就是1/12微秒。 【状态周期】:单片机完成一个最基本的动作所需的时间周期。如扫描一次定时器T0引脚状态所需要的时间。一个状态周期=2个振荡周期。 【机器周期】:单片机完成一次完整的具有一定功能的动作所需的时间周期。如一次完整的读操作或写操作对应的时间。一个机器周期=6个状态周期。 【指令周期】:执行完某条指令所需要的时间周期,一般需要1~4个机器周期,如MUL AB指令是四机器周期指令。一个指令周期=1~4个机器周期。 单片机工作时,除了需要时钟支持外,还必须有一个初始状态,即单片机的复位状态。在单片机外部引脚第9脚,就是专门给单片机提供复位脉冲的。 Pin9:RESET/Vpd复位信号复用脚,当89S51通电,时钟电路开始工作,在RESET 引脚上出现24个时钟周期以上的高电平,系统即初始复位。

自制单片机烧写器

像我们这样搞电子的人,要的就是动手的乐趣。下面我们来介绍近期在网络上非常流行的USBasp下载线,因为现在的笔记本包括台式机都渐渐地舍弃了并口、串口;所以之前的并口或串口下载线已经不能再使用了,应该说是做个USBasp下载线是势在必行的,下面我们来介绍其制作的全过程。 图(1) 图1为原作者设计的原理图,为了便于制作我修改过某部分电路如图2,其功能一样。

图(2) 在制作之前首先要搞清楚几点: 第一、这个USB下载线本身就是一块AVR单片机,在制作过程中也必需对其进行程序下载才能运行。 第二、先得大概了解一下这个AVR单机机ATmega8的基本资料。这样才能对电路有个了解,从而便于调试。第三COM1是PC机与USB相接的端口,我们在焊接时一定要区分GND、VCC、D+、D-,下面图(3)是对应本次制作的USB端口的引脚功能。在焊接的之前务必搞清楚,否则会造成PC机端口的USB或下载给的ATmega8烧毁。

图(3)USB端口引脚功能 第四﹑最后我们来了解一下电路的结构。对应图2,其中JP1是选择下载时的速度是快速或慢速,当JP1接地时选择低速,否则为高速。对于选择快速还是慢是相对于被下载的单片机晶振时钟而言的。一般来讲,目标单片机与USBasp的ATmega8的时钟不能相差太远。而JP2是电源的选择,当短接时被下载的单片机选择USBasp供电,则否选择独立供电。切记:两者只能任选其一。LED2为ATmega8程序运行的指示灯,当其点亮时就证明USBasp运行正常。LED1为下载程序时的工作指示灯,当接收到上位机信号

时,此灯就会闪动。 图(4)制作的全部元器件 图(5_a)与图2对应的PCB板顶层

如何将程序代码烧录进STC单片机

不能用keil作下载,它应该只是一个程序编辑和调试用的吧,用keil生成hex 文件。下载时用专门的下载软件找到生成的那个hex文件就可以下载了。,有专门的单片机烧写软件的。那个软件的名字叫STC-ISP V391(你可以下载个更高版本的)的,你的开发板里面应该自带下载软件的啊! 如果你用的下载下是USB转串口的线的话,你需要安装一个USB转串口驱动才能下载程序。网上搜一下就可以了。如果有光盘的话就在光盘里面找,里面肯定有的。 如何将程序代码烧录进STC单片机 先安装<STC单片机编程工具>软件到计算机中,然后进行下面的操作。 以下是烧录程序的主要界面。烧录过程非常简单,操作也非常简单。图中红色的五个大数字就表示了整个过程。简简单单的五步就可以了(实际上只需4步)。 启动本烧录程序后,第一步就是选择烧录器件。本烧录软件支持STC全系列的51单片机芯片,因此,第一步必须选择相对应的型号。由于本实验板选用的单片机芯片就是本烧录

软件首次启动默认的型号,所以,本项一般都不需要选择。 另外,“AP Memory”是指该芯片的内存大小和起止地址,根据器件型号自动更改,不必理会。 选择了器件型号,第二步就应该选择将要被烧录的HEX机器码文件。HEX文件由单片机开发环境输入、编辑代码,最后编绎产生。

至于如何产生HEX文件,很多资料也都有介绍,本板光盘中有详细的说明,并且提供了多套开发软件(每套都能用)。通过对照自学完全可以很快掌握操作。并且,本实验板光盘也提供了多种单片机开发环境供大家学习研究。 本光盘中提供了一些例子程序,大家可以点“open file”按钮,弹出以下窗口(源程序也有,但这里不显示),先选择一些例子程序烧录实验。 选好了文件后,大家可以发现“文件校验和”中的数据发生了变化,大家可以通过留意这个数据是否变化来确定打开文件是否成功,或者文件刷新是否有更改。 当然,文件打开后,会显示在右边的数据区,大家也可以观查右边数据区是否有更改。不过,当数据太多时,更改的地方又很少时,观查“文件校验和”会更快更准确。 选好了器件,选好了文件,第三步就可以设置串口和串口通信速度了。串口是一个九针的插座,老式的鼠标口就是串口。为了让通信可靠,我们可以适当的选低一些的速度,这个串口线较长时非常重要。 烧录过程中,如果出现失败,可以考虑将串口通信速度降低再试,这是由于机器配置以及当地环境因素决定的,当环境干扰过大时,必需选低一点的波特率(即通信速率)。烧录成功与失败,可以从信息区的提示看出。 选择并设置好串口后(一般不需更改),进入第四步,而这一步基本上不用更改。设置时钟倍频主要是为了提高工作速度,设置时钟增益是为了降低电磁幅射。这些,对于高级工程人员和最终产品会很有用,对于初学者来说,只当没有看见就行了。 第五步是最后一步,点击“Download/下载”,就可以进入烧录状态。 特别说明:点击“Download/下载”之前实验板的电源开关必须关闭,使单片机彻底断电,点击“Download/下载”之后才可以使单片机上电,完成程序的烧录。 注意:点击“Re-Download/重复下载”也可以,这常用于大批量的编程,不必每次都去点“Download/下载”。出现以下图状态时,给实验板通电就可以完成编程过程(如果实验板已经通电,则必须关掉电源1秒钟再次通电)。

单片机各种烧写文件格式简介

各种烧写文件格式简介-ELF Hex Bin 一,ELF Executable and linking format(ELF)文件是x86 Linux系统下的一种常用目标文件(object file)格式,有三种主要类型: Executable and linking format(ELF)文件是x86 Linux系统下的一种常用目标文件(object file)格式,有三种主要类型: (1)适于连接的可重定位文件(relocatable file),可与其它目标文件一起创建可执行文件和共享目标文件。 (2)适于执行的可执行文件(executable file),用于提供程序的进程映像,加载的内存执行。 (3)共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件,动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。 ELF文件格式比较复杂。 二,hex 什么是Intel HEX格式? Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录 由十六进制数组成的机器码或者数据常量,Intel HEX文件经常被用于将程序或数据传输 存储到ROM.EPROM,大多数编程器和模拟器使用Intel HEX文件. 记录格式 一个Intel HEX文件可以包含任意多的十六进制记录,每条记录有五个域,下面是一个记录的格式. :llaaaatt[dd...]cc 每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描述. :冒号是每一条Intel HEX记录的开始 ll 是这条记录的长度域,他表示数据(dd)的字节数目. aaaa 是地址域,他表示数据的起始地址 <如果是数据记录,这表示将要烧录的这条记录中的数据在EPROM中的偏移地址,

简单C语言程序的例子

例子: #include main () { tips(); /*caller*/ printf(“\n Success is about banging on after others have let go”); } tips() /*caller*/ { printf (“\n When you reach the end of the rope tie a knot & hang on”,)0; } [上述程序的输出结果如下: When you reach the end of the ropt tie a knot & hang on. Success is about hanging on after others have let go.] #include main() { int a,fact; printf(“\nEnter any number”); scanf(“%d”,&a); fact=rec(a); printf(“Factorial value is%d”,fact); } rec(x); int x; { int f; if(x==1) return(1); else f=x*rec(x-1); return(f); } [其显示的结果为:Factorial value is 2.] 比较两个数较大的那个: #include main()

{ int a,b,max; scanf (“%d%d”,&a,&b); if (a>b) max=a; else max=b; printf (“%d”,max); } 输出a+b的值: #include void main() { int a,b,x; scanf (“%d%d”,&a,&b); x=a+b; printf (“%d”,x); } 输出a,b中最大的一位数: #include int max(int x,int y) { int z; if (x>y) z=x; else z=y; return(z); } void main() { int a,b,c; scanf (“%d%d”,&a,&b); c=max(a,b); printf (“%d\n”,c); } 输出Hello: #include int main() { printf (“Hello!”);

51单片机多任务运行

51单片机多任务运行 最近发现有的幺弟在对系统的内核感兴趣,加上我也是部分内核的初学者,突然来兴,便用了两天写了一个简单的内核。这个内核简单得不能再简单了,加上空格行、大括号和详细的注解只有246行,还带了4个点亮LED的任务。至今为止我所见最简单的内核~~~ 就跟这个内核取个“多任务分时处理内核”吧!这个内核和ucos系统思想有很大的差异,但是能够帮助我们学习理解ucos系统,能够帮我们了解51的内部结构,以及大多数的单片机运行处理数据的原理~~~ 好废话就不说啦!希望我们能互相学习共同进步 1、先来讲讲原理: 首先,我们看书时会知道51单片机在执行中断的时候,会有以下几个步骤和几种情况。 根据KEIL的编译惯例(这个编译惯例你可以在编完程序后点仿真,里面有个后缀为.src 的文件,这个文件里面是一句C对应一句汇编,你就可以知道你编译的C代码它是怎么处理的,能帮助你学习汇编哦~~~),通常把进入中断后的所使用的通用寄存器组根据情况选择压栈。也就是说,中断前后使用的寄存器组可能不一样,中断前可能使用0,中断中可能使用1。如果使用的同一组寄存器,为了保存现场,KEIL就PUSH现场数据,然后POP 就行啦。但是keil很多时候不是你想象中那样,你叫它怎样他就怎样编译。所以在程序中嵌入了少量的汇编。 其实,嵌入汇编是很简单的事情。 只要在C代码中加入#pragma asm 和#pragma endasm并在他俩的中间加入汇编就行。别忘了还要在工程文件中添加C51S.LIB,这个文件在KEIL/C51/LIB中,这个文件也很重要,不然编译会出现警告,记得把文件类型选择为全部文件,不然看不见它。 接下来说说KEIL的中断汇编。在C51中,中断到来时,CPU响应中断保存当前PC 指针地址压栈SP所指地址。然后将PC指针指向中断向量地址,在中断向量地址中只有一句汇编程序:LJMP XX 意思是跳转到某地址。因为中断后只有8个寄存器,但是你的代码量远远不只有8个寄存器能装下的。这也就是说,响应中断后,先跳转到硬件规定的地址,再由那个地址跳转到中断程序入口。 然后,PC指针跳转到中断程序地址,开始从SP所指地址压栈ACC,B,DPH,DPL,PSW,按理说还需要压栈R0~R7,但KEIL一般是通过换通用寄存器来实现的(也就是改变RS1和RS0来实现的)。也就说KEIL根本不压栈R0~R7。 这个怎么能行,当然不行!不保存我们就不能完全的返回先前压栈的任务啦!好吧,那我们就只有手动保存压栈,这样不就行了,简单吧! 所以我们来帮它。已经通过前面知道它在进入中断的时候已经把中断前的PC指针压栈到中断前SP所指的地址了,所以进入中断后,实际在SP中断前所指地址中已经按顺序压栈了PC低8位,PC高8位,ACC,B,DPH,DPL,PSW总共7个数据,SP是向上增长的,也就是说每压一次堆栈SP+1。然后再把我们的R0~R7寄存器压入堆栈,这不就行啦,就保护现场所需的全部数据,就算有时R0~R7寄存器用不上我们也得加进去,为了为了保证正确的返回现场。 因此我们保存一次数据就需要7+8=15字节的堆栈,每个任务的起始地址保存一次,中间临时要保存一次,共需要15+15=30字节的堆栈。所以定义程序空间为现场保存空间为 0~29。名字叫:unsigned char TASK_STACK[TASK_MAX][30];//程序现场保存数组。TASK_MAX是程序个数,因为每一个程序都需要保存两次,每次15个变量来保存现场,并且51是8位的单片机所以用unsigned char。 然后就是程序现场保存数组的初始化使每个数据都是0。 首先,根据响应中断后的压栈顺序,知道了数组0位和1位保存的是中断前程序的地

第三章 最简单的c程序设计

第三章最简单的c程序设计 实践教学: 属性:实训 时间:学时。 实践教学内容: 实验目的:熟悉运算符、表达式,掌握标准输入输出函数的适用方法和顺序结构程序设计的一般方法。 实验内容和步骤: 1.编程,要求从键盘按规定的格式输入时间(时:分:秒), 并将输入的时间在屏幕上显示出来,存入ex3_1.c文件, 并编译、调试、运行。 #include main() { int a ,b,c; scanf("%d%d%d",&a,&b,&c); if (a>24) printf("请重新输入"); if (b>60) printf("请重新输入"); if (c>60) printf("请重新输入"); printf("%d:%d:%d\n",a,b,c); return 0; }

2.编程,要求从键盘输入数据,使整型变量a=10,b=8;字符 型c1=’A’,c2=’a’;实型变量x=3.1,y=64.54。并按规定格式输出变量的值。格式如下。存入ex3-2.c文件,并编译、调试、运行。 __int___a=__10___b=____8 char_c1=__A,___c2=____a float___x=_3.1,___y=64.54 #include main() { int a=10,b=8; char c1='A',c2='a'; float x=3.1,y=64.54; return 0; } 3.c语言编程求ax2+bx+c=0并分析其结果。存入ex3_2.c文 件,并编译、调试、运行。 #include

STC系列单片机程序烧录方法

S T C系列单片机程序烧 录方法 -CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN

STC系列单片机程序烧录方法 来源:互联网作者: 关键字:STC单片机 ??单片机烧录 ??单片机烧录方法 ?? STC单片机具有通过串口编程功能,简单到通过串口3三根线就能将程序烧录到单片机内,这大大的方便了开发人员,省去了昂贵复杂的编程器,在调试程序时也可将内部数据直接通过串口发送到PC上观看,一些不太复杂的程序甚至可以省掉仿真器。 目前大部分的计算机都不带串口,这里还得介绍一下一个小转换工具,可将PC上的USB口转换成单片机的TTL电平。插入硬件后提示安装驱动,完成后查看PC上设备管理器,端口中会多出一个串口,这里是COM3,记住这个串口号,下面给单片机烧录是要用。

单片机板和转换板连线对应连接好,如发现无法通讯,可调整2、3的连线。 1,地线----地线 2,TXD-----RXD 3,RXD-----TXD 转换板由于PC供电,指对外提供很小的供电能力,建议单片机板用单独的电源供电,切记不能外接电源和转换板同时对单片机板供电,否则会烧设备或计算机的危险。 硬件连接正常后就是通过STC专门的烧录软件进行烧录了。

1、现在对应的单片机型号 2、打开编译过的需要写入单片机内的程序,类型都是以.bin和.Hex 结尾的文件。 3、选择连接的串口号,就是上边在设备管理器里看到的COM3。 4、选择通讯波特率,单片机目标板上有晶振的,这一项基本可以不用理会,系统会自动适应合适的波特率。如果目标板使用的是内部振荡,由于内部制造误差,自动波特率可能会连接不成功,这时就要手工

松翰单片机的OTP可重复烧写的技巧!

松翰单片机的OTP可重复烧写的技巧! 1.问题:笔者在前期工作中,常常遇到在做测试时,只要修改一些简短的指令或数据时,就要再换一个全新的芯片重新烧录一下,再测试。这样即浪费时间,又消费芯片,还消费金钱呢。 2.解决:其实OTP不是你想象的那么“顽固”,只要你对它好一些,还是有些回报的。在烧录前,芯片的内部全是由2进制的1组成,烧录后,是对里面的1进行切断成0,如此,烧录过的不能再烧录,是对已经把1烧录成0的不可再烧,而是没有把1烧成0的,还是可以再烧的。也就是说,1可以变成0,而0不可再变为1,就象保险丝一样,烧断了就不可再烧,而没烧断的,你还可以把它烧断。要想实现重烧的过程,还是要有些技巧的。哎,废话这么多,来些实例的讲吧。 你可以在你想要的地方预留些空间,等你想要在这修改时,再从里面提取出来。 ;-----------------------------------------------------------------------------; 3.实例1:在已经烧过程序的IC上修改数据: incms t_enter_io ;500ms 进入一次 nop ; mov a,#0xFF ;1 预留数据修改(二进制为:b) mov a,#0xFF ;2 预留数据修改 mov a,#0xFF ;3 预留数据修改 mov a,#0xFF ;4 预留数据修改

mov a,#0xFF ;5 预留数据修改 mov a,#0xF3 ;等待被修改的数据 cjb t_enter_io,a,e_tele_io ;249次进入一下 clr t_enter_io ; ;-----------------------------------------------------------------------------; 3.1.1 (直接修改)比如我想在已经烧有上面程序的IC的基础上,修改a=0xF3(2二进制:B)为a=0xF1,此时,你就不要再浪费IC了,直接在上面修改就可以。你可以看到,0xF3与0xF1的区别只在于3和1,二进制为:0011B和0001B,所以你可以把0011B(十进制3)中第2位的1修改为0,即从0011B成为0001B,所以可以直接修改,当然你也要以把它修改成为你想要的数据,但前提是:你只能从二进制中的1烧成0,不可从0变为1. 比如我可以把0xF1再烧成0xA1或0xA0或0x01或0x00等等。 ;-----------------------------------------------------------------------------; (覆盖修改)是否有一种可以在上面的程序中任意修改数据呢这是有的!读者可以看到,我上面的程序为了防止修改不同的数据而所预留的5条 :mov a,0xFF ,这是为了修改各种数据而预留的。你可以把 0xFF(二进制:B)修改成0~255范围的任意一个数据。修改过程为:先把在最下面的不想要的数据(直接送数指令:mov a,0xF3 ;此指令生成的机器指令为:2DF3),用 NOP(机器指令为:0000 )给填充掉。然后第5条的0xFF修改为你想要的数据),比如修改为:0x45,修改后的程序如下: incms t_enter_io ;500ms 进入一次 nop ; mov a,#0xFF

简单C语言程序的例子

简单C语言程序的例子 Prepared on 22 November 2020

例子: #include<> main() { tips();/*caller*/ printf(“\nSuccessisaboutbangingonafterothershaveletgo”); } tips()/*caller*/ { printf(“\nWhenyoureachtheendoftheropetieaknot&hangon”,)0; } [上述程序的输出结果如下:Whenyoureachtheendoftheropttieaknot&hangon. Successisabouthangingonafterothershaveletgo.] #include<> main() { inta,fact; printf(“\nEnteranynumber”); scanf(“%d”,&a); fact=rec(a); printf(“Factorialvalueis%d”,fact); } rec(x); intx; { intf; if(x==1) return(1); else f=x*rec(x-1); return(f); } [其显示的结果为:Factorialvalueis2.] 比较两个数较大的那个: #include<> main() { inta,b,max;

scanf(“%d%d”,&a,&b); if(a>b) max=a; elsemax=b; printf(“%d”,max); } 输出a+b的值: #include<> voidmain() { inta,b,x; scanf(“%d%d”,&a,&b); x=a+b; printf(“%d”,x); } 输出a,b中最大的一位数:#include<> intmax(intx,inty) { intz; if(x>y)z=x; elsez=y; return(z); } voidmain() { inta,b,c; scanf(“%d%d”,&a,&b); c=max(a,b); printf(“%d\n”,c); } 输出Hello: #include<> intmain() { printf(“Hello!”); return0; } 求1~100的和: #include<>

简单的C程序介绍

简单的C程序介绍 例1: main()主函数说明 { 程序框架 printf(“abcdef”);函数体 } 语句 程序的功能是输出字符串:abcdef 例2:求两数之和。 main() { int a,b,c; a a=100; b=50; b c=a+b; c printf(“\n c=%d”,c); } 程序运行结果:c=150 例3:求两数中的最大值。函数类型函数名形参 main() int max (int x,int y) { int a,b,c; { int z; scanf(“%d,%d”,&a,&b); if(x>y) z=x; c=max(a,b); else z=y; printf(“\nmax is:%d”,c); return(z); } } a x b y c z (两个函数组成) C 的数据类型 ●基本类型(整型、实型、字符型、枚举型) ●构造类型(略) ●指针类型(略) ●空类型各类型包含常量与变量

3.2 常量与变量 ■常量与符号常量 常量 在程序运行过程中其值保持不变的量。 符号常量 用来代表一个常量的标识符。 #define PI 3.1415926 例: #define PI 3.1415926 main() { float r=2,c; c=2*PI*r; printf(“%f”,c); } ■变量 其值可以改变的量。 变量的三要素: ①变量名 每个变量有一个名字,作为识别该变量的标识符。 ②变量的值 每个变量有一个值,变量的值是随时可以改变的。 ③变量的存储单元 每个变量占据一个内存单元,用于存放变量的值。 变量名 a 变量值 存储单元 变量的命名规则: 由字母、数字和下划线组成 以字母或下划线开头

实验项目:实验一 最简单的C程序设计

实验项目:实验一最简单的C程序设计 (所属课程:《C语言程序设计》学时:2) 一、实验目的 1.掌握:使用标准输入/输出函数进行常见数据类型的数据的输入/输出方法。 2.初步培养编制程序框图和源程序、准备测试数据以及实际调试程序的独立编程能力。 3.掌握顺序结构程序设计的基本思路。 二、实验条件 Pc和vc++编程环境 三、实验内容 1.熟悉编程环境。 2.输入并运行一个C程序 3.掌握各种格式转换符的正确使用方法。 4.编程序:设圆半径r=1.5,圆柱高h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。要求用scanf函数从键盘上输入数据(半径和高),输出各计算结果,输出时要求有文字说明,取小数点后2位数字。5.编程序:用getchar函数输入两个字符给C1、C2,然后分别用putchar 函数和printf函数输出这两个字符。 四、实验步骤 编写程序,输入数据,观察结果。 五、实验结果 观察结果和预期是否一致。 实验项目:实验二选择结构程序设计

(所属课程:《C 语言程序设计》学时:2) 一、实验目的 1.了解C 语言表示逻辑量的方法(以0代表“假”,以非0代表“真”)。 2.学会正确使用逻辑运算符和逻辑表达式。 3.熟练掌握if 语句和switch 语句 二、实验条件 Pc 和vc++编程环境 三、实验内容 1.有一函数: ?? ???≥-<≤-<=)10x (113x )10x 1(12x )1x (x y 用scanf 函数输入x 的值,求y 值。 运行程序,输入x 的值(分别为x<1、1≤x <10、x ≥10三种情况),检查输出的y 值是否正确。 2.给出一个百分制成绩,要求输出成绩等级A 、B 、C 、D 、E 。90分以上为A ,81~89分为B ,71~79分为C ,61~69分为D ,60分以下为E 。 3.输入4个整数,要求按由小到大顺序输出。 四、实验步骤 编写程序,输入数据,观察结果。 五、实验结果 观察结果和预期是否一致。 实验项目:实验三 循环结构程序设计

51单片机的看门狗

“看门狗”概念及其应用 在由单片机构成的系统中,由于单片机的工作有可能会受到来自外界电磁场的干扰,造成程序的跑飞,从而陷入死循环,程序的正常运行被打断,由单片机控制的系统便无法继续工作,这样会造成整个系统陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的芯片,俗称“看门狗”(watch dog)。 加入看门狗电路的目的是使单片机可以在无人状态下实现连续工作,其工作过程如下:看门狗芯片和单片机的一个I/O引脚相连,该I/O引脚通过单片机的程序控制,使它定时地往看门狗芯片的这个引脚上送入高电平(或低电平),这一程序语句是分散地放在单片机其他控制语句中间的,一旦单片机由于干扰造成程序跑飞后而陷入某一程序段进入死循环状态时,给看门狗引脚送电平的程序便不能被执行到,这时,看门狗电路就会由于得不到单片机送来的信号,便将它和单片机复位引脚相连的引脚上送出一个复位信号,使单片机发生复位,从而单片机将从程序存储器的起始位置重新开始执行程序,这样便实现了单片机的自动复位。 通常看门狗电路需要一个专门的看门狗芯片连接单片机来实现,不过这样会给电路设计带来复杂,STC单片机内部自带有看门狗,通过对相应特殊功能寄存器的设置就可实现看门狗的应用,STC89系列单片机内部有一个专门的看门狗定时器寄存器,Watch Dog Timer 寄存器,其相应功能见下个知识点。 看门狗定时器寄存器(WDT_CONTR) STC单片机看门狗定时器寄存器在特殊功能寄存器中的字节地址为E1H,不能位寻址,该寄存器用来管理STC单片机的看门狗控制部分,包括启停看门狗、设置看门狗溢出时间等。单片机复位时该寄存器不一定全部被清0,在STC下载程序软件界面上可设置复位关看门狗或只有停电关看门狗的选择,大家根据需要可做出适合自己设计系统的选择。其各位的定义如表4.2.1所示。 表1看门狗定时器寄存器(WDT_CONTR)

C语言 实验五 最简单的C语言程序设计

实验5:最简单的C语言程序设计 一、实验目的: (1)掌握C语言中使用最多的一种语句——赋值语句的使用方法。(2)掌握各种类型数据的输入输出的方法,能正确使用各种格式转换符。(3)进一步掌握编写程序和调试程序的方法。 二、实验内容和步骤: 1、通过下面的程序掌握各种格式转换符的正确使用方法。 (1)输入以下程序: /* Note:Your choice is C IDE */ # include int main( ) {int a,b; float d,e; char c1,c2; double f,g; long m,n; unsigned int p,q; a=61,b=62; c1='a';c2='b'; d=3.56;e=-6.87; f=3157.890121;g=0.123456789; m=50000;n=-60000; p=32768;q=40000; printf("a=%d,b=%d\nc1=%c,c2=%c\nd=%6.2f,e=%6.2f\n",a,b,c1,c2,d,e); printf("f=%15.6f,g=%15.12f\nm=%1d\np=%u,q=%u\n",f,g,m,n,p,q); 显示结果: (2)运行此程序并分析结果。 (3)在此基础上,将程序第10~14行改为c1=a,c2=b; f=3157.890121;g=0.123456789; d=f;e=g;运行程序,分析结果。 /* Note:Your choice is C IDE */ #include"stdio.h"

int main() {int a,b; float d,e; char c1,c2; double f,g; long m,n; unsigned int p,q; a=61;b=62; c1=a;c2=b; f=3157.890121;g=0.123456789; d=f;e=g; p=a=m=50000;q=b=n=-60000; printf("a=%d,b=%d\nc1=%c,c2=%c\nd=%6.2f,e=%6.2f\n",a,b,c1,c2,d,e); printf("f=%15.6f,g=%15.12f\nm=%1d,n=%1d\np=%u,q=%u\n",f,g,m,n,p,q); } 显示结果: (4)用sizeof运算符分别检测程序中各类型的数据占多少字节。例如,int型变量a的字节数为sizeof(a)或sizeof(int),用printf函数语句输出各类型变量的长度(字节数)。 程序如下: # include int main( ) {printf("int:%d\n",sizeof(int)); return 0; } 显示结果: #include int main( ) {printf("float:%d\n",sizeof(float)); return 0; }

相关文档
最新文档