当前位置:文档之家› C51单片机C语言学习入门资料

C51单片机C语言学习入门资料

C51单片机C语言学习入门资料
C51单片机C语言学习入门资料

前言............................................................... 错误!未定义书签。

基础知识:单片机编程基础 (1)

第一节:单数码管按键显示 (3)

第二节:双数码管可调秒表 (5)

第三节:十字路口交通灯 (6)

第四节:数码管驱动 (8)

第五节:键盘驱动 (9)

第六节:低频频率计 (14)

第七节:电子表 (17)

第八节:串行口应用 (18)

基础知识:单片机编程基础

单片机的外部结构:

1、DIP40双列直插;

2、P0,P1,P2,P3四个8位准双向I/O引脚;(作为I/O输入时,要先输出高电平)

3、电源VCC(PIN40)和地线GND(PIN20);

4、高电平复位RESET(PIN9);(10uF电容接VCC与RESET,即可实现上电复位)

5、内置振荡电路,外部只要接晶体至X1(PIN18)和X0(PIN19);(频率为主频的12倍)

6、程序配置EA(PIN31)接高电平VCC;(运行单片机内部ROM中的程序)

7、P3支持第二功能:RXD、TXD、INT0、INT1、T0、T1

单片机内部I/O部件:(所为学习单片机,实际上就是编程控制以下I/O部件,完成指定任务)

1、四个8位通用I/O端口,对应引脚P0、P1、P2和P3;

2、两个16位定时计数器;(TMOD,TCON,TL0,TH0,TL1,TH1)

3、一个串行通信接口;(SCON,SBUF)

4、一个中断控制器;(IE,IP)

针对AT89C52单片机,头文件AT89x52.h给出了SFR特殊功能寄存器所有端口的定义。教科书的160页给出了针对MCS51系列单片机的C语言扩展变量类型。

C语言编程基础:

1、十六进制表示字节0x5a:二进制为01011010B;0x6E为01101110。

2、如果将一个16位二进数赋给一个8位的字节变量,则自动截断为低8位,而丢掉高8位。

3、++var表示对变量var先增一;var—表示对变量后减一。

4、x |= 0x0f;表示为 x = x | 0x0f;

5、TMOD = ( TMOD & 0xf0 ) | 0x05;表示给变量TMOD的低四位赋值0x5,而不改变TMOD的高四位。

6、While( 1 ); 表示无限执行该语句,即死循环。语句后的分号表示空循环体,也就是{;}

在某引脚输出高电平的编程方法:(比如P1.3(PIN4)引脚)

#include //该头文档中有单片机内部资源的符号化定义,其中包含P1.3

void main( void ) //void 表示没有输入参数,也没有函数返值,这入单片机运行的复位入口{

P1_3 = 1; //给P1_3赋值1,引脚P1.3就能输出高电平VCC

While( 1 ); //死循环,相当 LOOP: goto LOOP;

}

注意:P0的每个引脚要输出高电平时,必须外接上拉电阻(如4K7)至VCC电源。

在某引脚输出低电平的编程方法:(比如P2.7引脚)

#include //该头文档中有单片机内部资源的符号化定义,其中包含P2.7

void main( void ) //void 表示没有输入参数,也没有函数返值,这入单片机运行的复位入口{

P2_7 = 0; //给P2_7赋值0,引脚P2.7就能输出低电平GND

While( 1 ); //死循环,相当 LOOP: goto LOOP;

}

在某引脚输出方波编程方法:(比如P3.1引脚)

#include //该头文档中有单片机内部资源的符号化定义,其中包含P3.1

void main( void ) //void 表示没有输入参数,也没有函数返值,这入单片机运行的复位入口{

While( 1 ) //非零表示真,如果为真则执行下面循环体的语句

{

P3_1 = 1; //给P3_1赋值1,引脚P3.1就能输出高电平VCC

P3_1 = 0; //给P3_1赋值0,引脚P3.1就能输出低电平GND

} //由于一直为真,所以不断输出高、低、高、低……,从而形成方波

}

将某引脚的输入电平取反后,从另一个引脚输出:(比如 P0.4 = NOT( P1.1) )

#include //该头文档中有单片机内部资源的符号化定义,其中包含P0.4和P1.1

void main( void ) //void 表示没有输入参数,也没有函数返值,这入单片机运行的复位入口{

P1_1 = 1; //初始化。P1.1作为输入,必须输出高电平

While( 1 ) //非零表示真,如果为真则执行下面循环体的语句

{

if( P1_1 == 1 ) //读取P1.1,就是认为P1.1为输入,如果P1.1输入高电平VCC

{

P0_4 = 0; //给P0_4赋值0,引脚P0.4就能输出低电平GND

}

else //否则P1.1输入为低电平GND

{

P0_4 = 1; //给P0_4赋值1,引脚P0.4就能输出高电平VCC

}

} //由于一直为真,所以不断根据P1.1的输入情况,改变P0.4的输出电平

}

将某端口8个引脚输入电平,低四位取反后,从另一个端口8个引脚输出:(比如 P2 = NOT( P3 ) )

#include //该头文档中有单片机内部资源的符号化定义,其中包含P2和P3

void main( void ) //void 表示没有输入参数,也没有函数返值,这入单片机运行的复位入口

{

P3 = 0xff; //初始化。P3作为输入,必须输出高电平,同时给P3口的8个引脚输出高电平While( 1 ) //非零表示真,如果为真则执行下面循环体的语句

{ //取反的方法是异或1,而不取反的方法则是异或0

P2 = P3^0x0f //读取P3,就是认为P3为输入,低四位异或者1,即取反,然后输出} //由于一直为真,所以不断将P3取反输出到P2

}

注意:一个字节的8位D7、D6至D0,分别输出到P3.7、P3.6至P3.0,比如P3=0x0f,则P3.7、P3.6、P3.5、P3.4四个引脚都输出低电平,而P3.3、P3.2、P3.1、P3.0四个引脚都输出高电平。同样,输入一个端口P2,即是将P2.7、P2.6至P2.0,读入到一个字节的8位D7、D6至D0。

第一节:单数码管按键显示

单片机最小系统的硬件原理接线图:

1、接电源:VCC(PIN40)、GND(PIN20)。加接退耦电容0.1uF

2、接晶体:X1(PIN18)、X2(PIN19)。注意标出晶体频率(选用12MHz),还有辅助电容30pF

3、接复位:RES(PIN9)。接上电复位电路,以及手动复位电路,分析复位工作原理

4、接配置:EA(PIN31)。说明原因。

发光二极的控控制:单片机I/O输出

将一发光二极管LED的正极(阳极)接P1.1,LED的负极(阴极)接地GND。只要P1.1输出高电平VCC,LED就正向导通(导通时LED上的压降大于1V),有电流流过LED,至发LED发亮。实际上由于P1.1高电平输出电阻为10K,起到输出限流的作用,所以流过LED的电流小于(5V-1V)/10K = 0.4mA。只要P1.1输出低电平GND,实际小于0.3V,LED就不能导通,结果LED不亮。

开关双键的输入:输入先输出高

一个按键KEY_ON接在P1.6与GND之间,另一个按键KEY_OFF接P1.7与GND之间,按KEY_ON后LED亮,按KEY_OFF后LED灭。同时按下LED半亮,LED保持后松开键的状态,即ON亮OFF灭。

#include

#define LED P1^1 //用符号LED代替P1_1

#define KEY_ON P1^6 //用符号KEY_ON代替P1_6

#define KEY_OFF P1^7 //用符号KEY_OFF代替P1_7

void main( void ) //单片机复位后的执行入口,void表示空,无输入参数,无返回值{

KEY_ON = 1; //作为输入,首先输出高,接下KEY_ON,P1.6则接地为0,否则输入为1

KEY_OFF = 1; //作为输入,首先输出高,接下KEY_OFF,P1.7则接地为0,否则输入为1 While( 1 ) //永远为真,所以永远循环执行如下括号内所有语句

{

if( KEY_ON==0 ) LED=1; //是KEY_ON接下,所示P1.1输出高,LED亮

if( KEY_OFF==0 ) LED=0; //是KEY_OFF接下,所示P1.1输出低,LED灭

} //松开键后,都不给LED赋值,所以LED保持最后按键状态。

//同时按下时,LED不断亮灭,各占一半时间,交替频率很快,由于人眼惯性,看上去为半亮态}

数码管的接法和驱动原理

一支七段数码管实际由8个发光二极管构成,其中7个组形构成数字8的七段笔画,所以称为七段数码管,而余下的1个发光二极管作为小数点。作为习惯,分别给8个发光二极管标上记号:a,b,c,d,e,f,g,h。对应8的顶上一画,按顺时针方向排,中间一画为g,小数点为h。

我们通常又将各二极与一个字节的8位对应,a(D0),b(D1),c(D2),d(D3),e(D4),f(D5),g(D6),h(D7),相应8个发光二极管正好与单片机一个端口Pn的8个引脚连接,这样单片机就可以通过引脚输出高低电平控制8个发光二极的亮与灭,从而显示各种数字和符号;对应字节,引脚接法为:a(Pn.0),b(Pn.1),c(Pn.2),d(Pn.3),e(Pn.4),f(Pn.5),g(Pn.6),h(Pn.7)。

如果将8个发光二极管的负极(阴极)内接在一起,作为数码管的一个引脚,这种数码管则被称为共阴数码管,共同的引

脚则称为共阴极,8

个正极则为段极。否

则,如果是将正极

(阳极)内接在一起

引出的,则称为共阳

数码管,共同的引脚

则称为共阳极,8个

负极则为段极。

以单支共阴数

码管为例,可将段极

接到某端口Pn,共阴

极接GND,则可编写

出对应十六进制码

的七段码表字节数据如右图:

16键码显示的程序

我们在P1端口接一支共阴数码管SLED,在P2、P3端口接16个按键,分别编号为KEY_0、KEY_1到KEY_F,操作时只能按一个键,按键后SLED显示对应键编号。

#include

#define SLED P1

#define KEY_0 P2^0

#define KEY_1 P2^1

#define KEY_2 P2^2

#define KEY_3 P2^3

#define KEY_4 P2^4

#define KEY_5 P2^5

#define KEY_6 P2^6

#define KEY_7 P2^7

#define KEY_8 P3^0

#define KEY_9 P3^1

#define KEY_A P3^2

#define KEY_B P3^3

#define KEY_C P3^4

#define KEY_D P3^5

#define KEY_E P3^6

#define KEY_F P3^7

Code unsigned char Seg7Code[16]= //用十六进数作为数组下标,可直接取得对应的七段编码字节

// 0 1 2 3 4 5 6 7 8 9 A b C d E F {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; void main( void )

{

unsigned char i=0; //作为数组下标

P2 = 0xff; //P2作为输入,初始化输出高

P3 = 0xff; //P3作为输入,初始化输出高

While( 1 )

{

if( KEY_0 == 0 ) i=0; if( KEY_1 == 0 ) i=1;

if( KEY_2 == 0 ) i=2; if( KEY_3 == 0 ) i=3;

if( KEY_4 == 0 ) i=4; if( KEY_5 == 0 ) i=5;

if( KEY_6 == 0 ) i=6; if( KEY_7 == 0 ) i=7;

if( KEY_8 == 0 ) i=8; if( KEY_9 == 0 ) i=9;

if( KEY_A == 0 ) i=0xA; if( KEY_B == 0 ) i=0xB;

if( KEY_C == 0 ) i=0xC; if( KEY_D == 0 ) i=0xD;

if( KEY_E == 0 ) i=0xE; if( KEY_F == 0 ) i=0xF;

SLED = Seg7Code[ i ]; //开始时显示0,根据i取应七段编码

}

}

第二节:双数码管可调秒表

解:只要满足题目要求,方法越简单越好。由于单片机I/O资源足够,所以双数码管可接成静态显示方式,两个共阴数码管分别接在P1(秒十位)和P2(秒个位)口,它们的共阴极都接地,安排两个按键接在P3.2(十位数调整)和P3.3(个位数调整)上,为了方便计时,选用12MHz的晶体。为了达到精确计时,选用定时器方式2,每计数250重载一次,即250us,定义一整数变量计数重载次数,这样计数4000次即为一秒。定义两个字节变量S10和S1分别计算秒十位和秒个位。编得如下程序:

#include

Code unsigned char Seg7Code[16]= //用十六进数作为数组下标,可直接取得对应的七段编码字节

// 0 1 2 3 4 5 6 7 8 9 A b C d E F {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; void main( void )

{

unsigned int us250 = 0;

unsigned char s10 = 0;

unsigned char s1 = 0;

unsigned char key10 = 0; //记忆按键状态,为1按下

unsigned char key1 = 0; //记忆按键状态,为1按下

//初始化定时器 Timer0

TMOD = (TMOD & 0xF0) | 0x02;

TH1 = -250; //对于8位二进数来说,-250=6,也就是加250次1时为256,即为0 TR1 = 1;

while(1){ //----------循环1 P1 = Seg7Code[ s10 ]; //显示秒十位

P2 = Seg7Code[ s1 ]; //显示秒个位

while( 1 ){ //----------循环2 //计时处理

if( TF0 == 1 ){

TF0 = 0;

if( ++us250 >= 4000 ){

us250 = 0;

if( ++s1 >= 10 ){

s1 = 0;

if( ++s10 >= 6 ) s10 = 0;

}

break; //结束“循环2”,修改显示

}

}

//按十位键处理

P3.2 = 1; //P3.2作为输入,先要输出高电平

if( key10 == 1 ){ //等松键

if( P3.2 == 1 ) key10=0;

}

else{ //未按键

if( P3.2 == 0 ){

key10 = 1;

if( ++s10 >= 6 ) s10 = 0;

break; //结束“循环2”,修改显示

}

}

//按个位键处理

P3.3 = 1; //P3.3作为输入,先要输出高电平

if( key1 == 1 ) //等松键

{ if( P3.3 == 1 ) key1=0; }

else { //未按键

if( P3.3 == 0 ){ key1 = 1;

if( ++s1 >= 10 ) s1 = 0;

break; //结束“循环2”,修改显示

}

}

} //循环2’end

}//循环1’end

}//main’end

第三节:十字路口交通灯

如果一个单位时间为1秒,这里设定的十字路口交通灯按如下方式四个步骤循环工作:

●60个单位时间,南北红,东西绿;

●10个单位时间,南北红,东西黄;

●60个单位时间,南北绿,东西红;

●10个单位时间,南北黄,东西红;

解:用P1端口的6个引脚控制交通灯,高电平灯亮,低电平灯灭。

#include

//sbit用来定义一个符号位地址,方便编程,提高可读性,和可移植性

sbit SNRed =P1^0; //南北方向红灯

sbit SNYellow =P1^1; //南北方向黄灯

sbit SNGreen =P1^2; //南北方向绿灯

sbit EWRed =P1^3; //东西方向红灯

sbit EWYellow =P1^4; //东西方向黄灯

sbit EWGreen =P1^5; //东西方向绿灯

/* 用软件产生延时一个单位时间 */

void Delay1Unit( void )

{

unsigned int i, j;

for( i=0; i<1000; i++ )

for( j<0; j<1000; j++ ); //通过实测,调整j循环次数,产生1ms延时

//还可以通过生成汇编程序来计算指令周期数,结合晶体频率来调整j循环次数,接近1ms

}

/* 延时n个单位时间 */

void Delay( unsigned int n ){ for( ; n!=0; n-- ) Delay1Unit(); }

void main( void )

{

while( 1 )

{

SNRed=0; SNYellow=0; SNGreen=1; EWRed=1; EWYellow=0; EWGreen=0; Delay( 60 );

SNRed=0; SNYellow=1; SNGreen=0; EWRed=1; EWYellow=0; EWGreen=0; Delay( 10 );

SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=0; EWGreen=1; Delay( 60 );

SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=1; EWGreen=0; Delay( 10 );

}

}

显示“12345678”

P1端口接8联共阴数码管SLED8的段极:P1.7接段h,…,P1.0接段a

P2端口接8联共阴数码管SLED8的段极:P2.7接左边的共阴极,…,P2.0接右边的共阴极

方案说明:晶振频率fosc=12MHz,数码管采用动态刷新方式显示,在1ms定时断服务程序中实现

#include

unsigned char DisBuf[8]; //全局显示缓冲区,DisBuf[0]对应右SLED,DisBuf[7]对应左SLED,void DisplayBrush( void )

{ code unsigned char cathode[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //阴极控制码Code unsigned char Seg7Code[16]= //用十六进数作为数组下标,可直接取得对应的七段编码字节{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

static unsigned char i=0; // (0≤i≤7)循环刷新显示,由于是静态变量,此赋值只做一次。

P2 = 0xff; //显示消隐,以免下一段码值显示在前一支SLED

P1 = Seg7Code[ DisBuf[i] ]; //从显示缓冲区取出原始数据,查表变为七段码后送出显示

P2 = cathode[ i ]; //将对应阴极置低,显示

if( ++i >= 8 ) i=0; //指向下一个数码管和相应数据

}

void Timer0IntRoute( void ) interrupt 1

{

TL0 = -1000; //由于TL0只有8bits,所以将(-1000)低8位赋给TL0

TH0 = (-1000)>>8; //取(-1000)的高8位赋给TH0,重新定时1ms

DisplayBrush();

}

void Timer0Init( void )

{ TMOD=(TMOD & 0xf0) | 0x01; //初始化,定时器T0,工作方式1

TL0 = -1000; //定时1ms

TH0 = (-1000)>>8;

TR0 = 1; //允许T0开始计数

ET0 = 1; //允许T0计数溢出时产生中断请求

}

void Display( unsigned char index, unsigned char dataValue ){ DisBuf[ index ] = dataValue; } void main( void )

{

unsigned char i;

for( i=0; i<8; i++ ){ Display(i, 8-i); } //DisBuf[0]为右,DisBuf[7]为左

Timer0Init();

EA = 1;//允许CPU响应中断请求

While(1);

}

指提供一些函数给任务调用,获取按键信息,或读取按键值。

定义一个头文档 ,描述可用函数,如下:

#ifndef _KEY_H_ //防止重复引用该文档,如果没有定义过符号 _KEY_H_,则编译下面语句

#define _KEY_H_ //只要引用过一次,即 #include ,则定义符号 _KEY_H_

unsigned char keyHit( void ); //如果按键,则返回非0,否则返回0

unsigned char keyGet( void ); //读取按键值,如果没有按键则等待到按键为止

void keyPut( unsigned char ucKeyVal ); //保存按键值ucKeyVal到按键缓冲队列末

void keyBack( unsigned char ucKeyVal ); //退回键值ucKeyVal到按键缓冲队列首

#endif

定义函数体文档 KEY.C,如下:

#include “key.h”

#define KeyBufSize 16 //定义按键缓冲队列字节数

unsigned char KeyBuf[ KeyBufSize ]; //定义一个无符号字符数组作为按键缓冲队列。该队列为先进

//先出,循环存取,下标从0到 KeyBufSize-1

unsigned char KeyBufWp=0; //作为数组下标变量,记录存入位置

unsigned char KeyBufRp=0; //作为数组下标变量,记录读出位置

//如果存入位置与读出位置相同,则表明队列中无按键数据

unsigned char keyHit( void )

{ if( KeyBufWp == KeyBufRp ) return( 0 ); else return( 1 ); }

unsigned char keyGet( void )

{ unsigned char retVal; //暂存读出键值

while( keyHit()==0 ); //等待按键,因为函数keyHit()的返回值为 0 表示无按键

retVal = KeyBuf[ KeyBufRp ]; //从数组中读出键值

if( ++KeyBufRp >= KeyBufSize ) KeyBufRp=0; //读位置加1,超出队列则循环回初始位置return( retVal );

}

void keyPut( unsigned char ucKeyVal )

{ KeyBuf[ KeyBufWp ] = ucKeyVal; //键值存入数组

if( ++KeyBufWp >= KeyBufSize ) KeyBufWp=0; //存入位置加1,超出队列则循环回初始位置}

/***************************************************************************************** 由于某种原因,读出的按键,没有用,但其它任务要用该按键,但传送又不方便。此时可以退回按键队列。就如取错了信件,有必要退回一样

******************************************************************************************/ void keyBack( unsigned char ucKeyVal )

{

/*

如果KeyBufRp=0; 减1后则为FFH,大于KeyBufSize,即从数组头退回到数组尾。或者由于干扰使得

KeyBufRp超出队列位置,也要调整回到正常位置,

*/

if( --KeyBufRp >= KeyBufSize ) KeyBufRp=KeyBufSize-1;

KeyBuf[ KeyBufRp ] = ucKeyVal; //回存键值

}

下面渐进讲解键盘物理层的驱动。

电路共同点:P2端口接一共阴数码管,共阴极接GND,P2.0接a段、P2.1接b段、…、P2.7接h段。

软件共同点:code unsigned char Seg7Code[10] 是七段数码管共阴编码表。

Code unsigned char Seg7Code[16]=

// 0 1 2 3 4 5 6 7 8 9 A b C d E F {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};

例一:P1.0接一按键到GND,键编号为‘6’,显示按键。

#include

#include “KEY.H”

void main( void )

{ P1_0 = 1; //作为输入引脚,必须先输出高电平

while( 1 ) //永远为真,即死循环

{ if( P1_0 == 0 ) //如果按键,则为低电平

{ keyPut( 6 ); //保存按键编号值为按键队列

while( P1_0 == 0 ); //如果一直按着键,则不停地执行该循环,实际是等待松键}

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

例二:在例一中考虑按键20ms抖动问题。

#include

#include “KEY.H”

void main( void )

{ P1_0 = 1; //作为输入引脚,必须先输出高电平

while( 1 ) //永远为真,即死循环

{ if( P1_0 == 0 ) //如果按键,则为低电平

{ delay20ms(); //延时20ms,跳过接下抖动

keyPut( 6 ); //保存按键编号值为按键队列

while( P1_0 == 0 ); //如果一直按着键,则不停地执行该循环,实际是等待松键

delay20ms(); //延时20ms,跳过松开抖动

}

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

例三:在例二中考虑干扰问题。即小于20ms的负脉冲干扰。

#include

#include “KEY.H”

void main( void )

{ P1_0 = 1; //作为输入引脚,必须先输出高电平

while( 1 ) //永远为真,即死循环

{ if( P1_0 == 0 ) //如果按键,则为低电平

{ delay20ms(); //延时20ms,跳过接下抖动

if( P1_0 == 1 ) continue; //假按键

keyPut( 6 ); //保存按键编号值为按键队列

while( P1_0 == 0 ); //如果一直按着键,则不停地执行该循环,实际是等待松键

delay20ms(); //延时20ms,跳过松开抖动

}

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

例四:状态图编程法。通过20ms周期中断,扫描按键。

/**************************************************************************************** 采用晶体为12KHz时,指令周期为1ms(即主频为1KHz),这样T0工作在定时器方式2,8位自动重载。计数值为20,即可产生20ms的周期性中断,在中断服务程序中实现按键扫描

*****************************************************************************************/ #include

#include “KEY.H”

void main( void )

{

TMOD = (TMOD & 0xf0 ) | 0x02; //不改变T1的工作方式,T0为定时器方式2

TH0 = -20; //计数周期为20个主频脉,即20ms

TL0=TH0; //先软加载一次计数值

TR0=1; //允许T0开始计数

ET0=1; //允许T0计数溢出时产生中断请求

EA=1; //允许CPU响应中断请求

while( 1 ) //永远为真,即死循环

{

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

void timer0int( void ) interrupt 1 //20ms;T0的中断号为1

{ static unsigned char sts=0;

P1_0 = 1; //作为输入引脚,必须先输出高电平

switch( sts )

{

case 0: if( P1_0==0 ) sts=1; break; //按键则转入状态1

case 1:

if( P1_0==1 ) sts=0; //假按错,或干扰,回状态0

else{ sts=2; keyPut( 6 ); } //确实按键,键值入队列,并转状态2

break;

case 2: if( P1_0==1 ) sts=3; break; //如果松键,则转状态3

case 3:

if( P1_0==0 ) sts=2; //假松键,回状态2

else sts=0; //真松键,回状态0,等待下一次按键过程}

}

例五:状态图编程法。

/****************************************************************************************

如果采用晶体为12MHz时,指令周期为1us(即主频为1MHz),要产生20ms左右的计时,则计数值达到20000,T0工作必须为定时器方式1,16位非自动重载,即可产生20ms的周期性中断,在中断服务程序中实现按键扫描

*****************************************************************************************/ #include

#include “KEY.H”

void main( void )

{

TMOD = (TMOD & 0xf0 ) | 0x01; //不改变T1的工作方式,T0为定时器方式1

TL0 = -20000; //计数周期为20000个主频脉,自动取低8位

TH0 = (-20000)>>8; //右移8位,实际上是取高8位

TR0=1; //允许T0开始计数

ET0=1; //允许T0计数溢出时产生中断请求

EA=1; //允许CPU响应中断请求

while( 1 ) //永远为真,即死循环

{

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

void timer0int( void ) interrupt 1 //20ms;T0的中断号为1

{ static unsigned char sts=0;

TL0 = -20000; //方式1为软件重载

TH0 = (-20000)>>8; //右移8位,实际上是取高8位

P1_0 = 1; //作为输入引脚,必须先输出高电平

switch( sts )

{

case 0: if( P1_0==0 ) sts=1; break; //按键则转入状态1

case 1:

if( P1_0==1 ) sts=0; //假按错,或干扰,回状态0

else{ sts=2; keyPut( 6 ); } //确实按键,键值入队列,并转状态2

break;

case 2: if( P1_0==1 ) sts=3; break; //如果松键,则转状态3

case 3:

if( P1_0==0 ) sts=2; //假松键,回状态2

else sts=0; //真松键,回状态0,等待下一次按键过程}

}

例六:4X4按键。

/**************************************************************************************** 由P1端口的高4位和低4位构成4X4的矩阵键盘,本程序只认为单键操作为合法,同时按多键时无效。这样下面的X,Y的合法值为0x7, 0xb, 0xd, 0xe, 0xf,通过表keyCode影射变换可得按键值

*****************************************************************************************/ #include

#include “KEY.H”

unsigned char keyScan( void ) //返回0表示无按键,或无效按键,其它值为按键编码值

{ code unsigned char keyCode[16]=

/0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF

{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 0 };

unsigned char x, y, retVal;

P1=0x0f; //低四位输入,高四位输出0

x=P1&0x0f; //P1输入后,清高四位,作为X值

P1=0xf0; //高四位输入,低四位输出0

y=(P1 >> 4) & 0x0f; //P1输入后移位到低四位,并清高四位,作为Y值

retVal = keyCode[x]*4 + keyCode[y]; //根据本公式倒算按键编码

if( retVal==0 ) return(0); else return( retVal-4 );

}

//比如按键‘1’,得X=0x7,Y=0x7,算得retVal= 5,所以返回函数值1。

//双如按键‘7’,得X=0xb,Y=0xd,算得retVal=11,所以返回函数值7。

void main( void )

{

TMOD = (TMOD & 0xf0 ) | 0x01; //不改变T1的工作方式,T0为定时器方式1

TL0 = -20000; //计数周期为20000个主频脉,自动取低8位

TH0 = (-20000)>>8; //右移8位,实际上是取高8位

TR0=1; //允许T0开始计数

ET0=1; //允许T0计数溢出时产生中断请求

EA=1; //允许CPU响应中断请求

while( 1 ) //永远为真,即死循环

{

if( keyHit() != 0 ) //如果队列中有按键

P2=Seg7Code[ keyGet() ]; //从队列中取出按键值,并显示在数码管上}

}

void timer0int( void ) interrupt 1 //20ms;T0的中断号为1

{ static unsigned char sts=0;

TL0 = -20000; //方式1为软件重载

TH0 = (-20000)>>8; //右移8位,实际上是取高8位

P1_0 = 1; //作为输入引脚,必须先输出高电平

switch( sts )

{

case 0: if( keyScan()!=0 ) sts=1; break; //按键则转入状态1

case 1:

if( keyScan()==0 ) sts=0; //假按错,或干扰,回状态0

else{ sts=2; keyPut( keyScan() ); } //确实按键,键值入队列,并转状态2

break;

case 2: if(keyScan()==0 ) sts=3; break; //如果松键,则转状态3

case 3:

if( keyScan()!=0 ) sts=2; //假松键,回状态2

else sts=0; //真松键,回状态0,等待下一次按键过程}

}

第六节:低频频率计

实例目的:学时定时器、计数器、中断应用

说明:选用24MHz的晶体,主频可达2MHz。用T1产生100us的时标,T0作信号脉冲计数器。假设晶体频率没有误差,而且稳定不变(实际上可达万分之一);被测信号是周期性矩形波(正负脉冲宽度都不能小于0.5us),频率小于1MHz,大于1Hz。要求测量时标1S,测量精度为0.1%。

解:从测量精度要求来看,当频率超过1KHz时,可采用1S时标内计数信号脉冲个数来测量信号频,而信号频率低于1KHz时,可以通过测量信号的周期来求出信号频率。两种方法自动转换。

对于低于1KHz的信号,信号周期最小为1ms,也就是说超过1000us,而我们用的定时器计时脉冲周期为0.5us,如果定时多计或少计一个脉冲,误差为1us,所以相对误差为1us/1000us=0.1%。信号周期越大,即信号频率越低,相对误差就越小。

从上面描述来看,当信号频率超过1KHz后,信号周期就少于1000us,显然采用上面的测量方法,不能达到测量精度要求,这时我们采用1S单位时间计数信号的脉冲个数,最少能计到1000个脉冲,由于信号频率不超过1MHz,而我们定时脉冲为2MHz,最差多计或少计一个信号脉冲,这样相对误差为1/1000,

可见信号频率越高,相对误差越小。

信号除输入到T1(P3.5)外,还输入到INT1(P3.3)。

unsigned int us100; //对100us时间间隔单位计数,即有多少个100us。unsigned char Second;

unsigned int K64; //对64K单位计数,即有多少个64K

unsigned char oldT0;

unsigned int oldus, oldK64, oldT1;

unsigned long fcy; //存放频率值,单位为Hz

bit HighLow=1; //1:表示信号超过1KHz;0:表示信号低于1KHz。void InitialHigh( void )

{

IE=0; IP=0; HighLow=1;

TMOD = (TMOD & 0xf0) | 0x02; TH0=-200; TL0=TH0; PX0=1; T0=1;

TMOD = (TMOD & 0x0f) | 0x50; TH1=0; TL1=0; T1=1; ET1=1;

Us100=0; Second=0; K64=0;

oldK64=0; oldT1=0;

TCON |= 0x50; //同时置 TR0=1; TR1=1;

EA = 1;

}

void InitialLow( void )

{

IE=0; IP=0; HighLow=0;

TMOD = (TMOD & 0xf0) | 0x02; TH0=-200; TL0=TH0; ET0=1; TR0=1;

INT1 = 1; IT1=1; EX1=1;

Us100=0; Second=0; K64=0;

oldK64=0; oldT1=0;

EA = 1;

}

void T0intr( void ) interrupt 1

{ if( HighLow==0 ) ++us100;

else

if( ++us100 >= 10000 )

{ unsigned int tmp1, tmp2;

TR1=0; tmp1=(TH1<<8) + (TL1); tmp2=K64; TR1=1;

fcy=((tmp2-oldK64)<<16) + (tmp1-oldT1);

oldK64=tmp1; oldT1=tmp2;

Second++;

us100=0;

}

}

void T1intr( void ) interrupt 3 { ++K64; }

void X1intr( void ) interrupt 2

{ static unsigned char sts=0;

switch( sts )

{

case 0: sts = 1; break;

case 1: oldT0=TL0; oldus=us100; sts=2; break;

case 2:

{

unsigned char tmp1, tmp2;

TR0=0; tmp1=TL0; tmp2=us100; TR0=1;

fcy = 1000000L/( (tmp2-oldus)*100L + (256-tmp1)/2 );

Second ++;

}

Sts = 0;

break;

}

}

void main( void )

{

if( HighLow==1) InitialHigh(); else InitialLow();

While(1)

{

if( Second != 0 )

{

Second = 0;

//display fcy 引用前面的数码管驱动程序,注意下面对T0中断服务程序的修改

{ unsigned char i;

for( i=0; i<8; i++ ){ Display(i, fcy%10); fcy /= 10; }

}

if( HighLow==1 )

if( fcy<1000L ){ InitalLow();}

else

if( fcy>1000L ){ InitalHigh();}

}

}

}

//修改T0的中断服务程序,让它在完成时标的功能时,同时完成数码管显示刷新

void T0intr( void ) interrupt 1

{

static unsigned char ms = 0;

if( HighLow==0 ) ++us100;

else

if( ++us100 >= 10000 )

{ unsigned int tmp1, tmp2;

TR1=0; tmp1=(TH1<<8) + (TL1); tmp2=K64; TR1=1;

fcy=((tmp2-oldK64)<<16) + (tmp1-oldT1);

oldK64=tmp1; oldT1=tmp2;

Second++;

us100=0;

}

if( ++ms >= 10 ){ ms=0; DisplayBrush(); } //1ms数码管刷新

}

第七节:电子表

单键可调电子表:主要学习编程方法。

外部中断应用,中断嵌

解:电子表分为工作状态和调整状态。平时为工作状态,按键不足一秒,接键为换屏‘S’。按键超过一秒移位则进入调整状态‘C’,而且调整光标在秒个位开始。调整状态时,按键不足一秒为光标移动‘M’,超过一秒则为调整读数,每0.5秒加一‘A’,直到松键;如果10秒无按键则自动回到工作状态‘W’。

如果有年、月、日、时、分、秒。四联数码管可分三屏显示,显示格式为“年月.”、“日.时.”、“分.秒”,从小数点的位置来区分显示内容。(月份的十位数也可以用“-”和“-1”表示)。

enum status = { Work, Change, Add, Move, Screen } //状态牧举

//计时和调整都是对下面时间数组Time进行修改

unsigned char Time[12]={0,4, 0,6, 1,0, 0,8, 4,5, 3,2};//04年06月10日08时45分32秒unsigned char cursor = 12; //指向秒个位,=0时无光标

unsigned char YmDhMs = 3; //指向“分秒”显示,=0时无屏显

static unsigned char sts = Work;

/*

如果cursor不为0,装入DisBuf的对应数位,按0.2秒周期闪烁,即设一个0.1秒计数器S01,S01为奇数时灭,S01为偶数时亮。

小数点显示与YmDhMs变量相关。

*/

void DisScan( void ) //动态刷新显示时调用。没编完,针对共阴数码管,只给出控控制算法

{

//DisBuf每个显示数据的高四位为标志,最高位D7为负号,D6为小数点,D5为闪烁

unsigned char tmp;

tmp = Seg7Code[?x & 0x1f ]; //设?x为显示数据,高3位为控制位,将低5位变为七段码if( ?x & 0x40 ) tmp |= 0x80; //添加小数点

if( ?x & 0x20 ){ if( S01 & 0x01 ) tmp=0; } //闪烁,S01奇数时不亮

//这里没有处理负号位

//将tmp送出显示,并控制对应数码管动作显示

}

void Display( void ) //根据状态进行显示

{

if( cursor != 0 ){ YmDhMs=(cursor+3)/4; } //1..4=1; 5..8=2; 9..12=3

for( i=(YmDhMs-1)*4; i<(YmDhMs)*4; i++ )

{ unsigned char j = i%4;

Disbuf[j] = Time[i];

if( i == (cursor-1) ) Disbuf[j] |= 0x20; //闪烁,cursor!=0时才闪烁

if( (i==9) || //小数点:分个位

(i==7) || //小数点:时个位

(i==5) || //小数点:日个位

(i==3) //小数点:月个位

) Disbuf[j] |= 0x40;

//if(i==2){ if(Time[2]==1) DisBuf[2]=“-1”; else DisBuf=“-”; } }

//工作状态:根据YmDhMs将屏数据装入DisBuf

//调整状态:根据cursor将屏数据装入DisBuf

}

void KeyScan( void ) //根据状态扫描按键

void ProcessKey( void ) //根据状态处理键信息

{

keyVal = KeyGet();

if( keyVal == 0 ) return;

switch( sts )

{

case Work:

if( keyVal ==‘S’)

{

if( --YmDhMs == 0 ) YmDhMs = 3; //换屏

}

if( keyVal == ‘C’)

{

sts = Change;

YmDhMs = 3;

Cursor = 12;

}

break;

case Change:

if( keyVal == ‘W’ )

if( keyVal == ‘A’ )

if( keyVal == ‘M’ ) //根据cursor

break;

}

}

第八节:串行口应用

一、使用晶体频率为22.1184MHz的AT89C52单片机,串行口应用工作方式1,以9600bps的波特率向外

发送数据,数据为十个数字‘0’到‘9’,循环不断地发送。

解:数字字符为增量进二进制码,‘0’对应0x30,‘1’= ‘0’+ 1 = 0x31,从‘0’到‘9’对应编码为0x30到0x39,记忆二进制编码较难,实际编程中用单引号括起对应字符表示引用该字符的

二进制编码值,如‘?’表示引用?号的编码值。

在用11.0592MHz晶体时,9600bps的初始化分频初值为-6,现晶频加倍,如果其它条件不变,只有分频初始加倍为-12,才能得到9600bps;如果想得到2400bps(速率降4倍),分频初始自然加大4倍,即为-48。根据题意编得如下程序:

#include

void main( void )

{

TMOD = (TMOD & 0x0F) | 0x20;

TH1 = -12;

PCON |= 0x80; //SMOD = 1

TR1 = 1;

SCON = 0x42;

while( 1 )

{

if( TI==1 )

{

static unsigned char Dat=‘0’;

SBUF = Dat;

TI = 0;

If( ++Dat > ‘9’) Dat=‘0’;

}

}

}

二、在上题的基础上,改为2400bps,循环发送小写字母‘a’到‘z’,然后是大写字母‘A’到‘Z’。

#include

void main( void )

{

TMOD = (TMOD & 0x0F) | 0x20;

TH1 = -96; //注意不用倍频方式

PCON &= 0x7F; //SMOD = 0

TR1 = 1;

SCON = 0x42;

while( 1 )

{

if( TI==1 )

{

static unsigned char Dat=‘a’;

SBUF = Dat;

TI = 0;

//If( ++Dat > ‘9’) Dat=‘0’;

++Dat;

if( Dat == (‘z’+1) ) Dat=‘A’;

if( Dat == (‘Z’+1) ) Dat=‘a’;

}

}

}

上述改变值时,也可以再设一变量表示当前的大小写状态,比如写成如下方式:

++Dat;

{

static unsigned char Caps=1;

if( Caps != 0 )

if( Dat>‘Z’){ Dat=‘a’; Caps=0; }

else

if( Dat>‘z’){ Dat=‘A’; Caps=1; }

}

如下写法有错误:因为小b比大Z的编码值大,所以Dat总是‘a’

++Dat;

if( Dat>‘Z’){ Dat=‘a’}

else if( Dat>‘z’){ Dat=‘A’}

三、有A和B两台单片机,晶体频率分别为13MHz和14MHz,在容易编程的条件下,以最快的速度进行双

工串行通信,A给B循环发送大写字母从‘A’到‘Z’,B给A循环发送小写字母从‘a’到‘z’,双方都用中断方式进行收发。

解:由于晶体频率不同,又不成2倍关系,所以只有通信方式1和方式3,由于方式3的帧比方式1多一位,显然方式3的有效数据(9/11)比方式1(8/10)高,但要用方式3的第9位TB8来发送数据,编程难度较大,这里方式1较容易编程。

在计算最高速率时,由于单方程,双未知数,又不知道波特率为多少,所以要综合各方面的条件,估算出A和B的分频常数,分别为-13和-14时,速率不但相同,且为最大值。如下给出A机的程序:#include

void main( void )

{

TMOD = (TMOD & 0x0F) | 0x20;

TH1 = -13; //注意用倍频方式

PCON |= 0x80; //SMOD = 1

TR1 = 1;

SCON = 0x52; //REN = 1

ES = 1;

EA = 1;

while( 1 );

}

void RS232_intr( void ) interrupt 4 //注意RI和TI任一位变为1都中断

{

unsigned char rDat;

if( RI == 1 ){ RI=0; rDat=SBUF; }

if( TI==1 )

{

static unsigned char tDat=‘a’;

SBUF = tDat;

TI = 0;

单片机C语言(非常通俗易懂)

单片机C语言(非常通俗易懂) (一) 相信很多爱好电子的朋友,对单片机这个词应该都不会陌生了吧。不过有些朋友可能只听说他叫单片机,他的全称是什么也许并不太清楚, 更不用说他的英文全称和简称了。单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。简称为:单片微型计算机或单片机 (Single Chip Computer)。单片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。不过这一切都没 什么关系,因为我(当然也包括任何人)都是从不知道转变成知道的,再转变成精通的。现在我只想把我学习单片机的经历,详细地讲叙给大 家听听,可能有些大虾会笑话我,想:那么简单的东西还在这里卖弄。但是你错了,我只是把我个人学习的经历讲述一遍而已,仅仅对那些想 学习单片机,但又找不到好方法或者途径的朋友,提供一个帮助,使他们在学习过程中,尽量少走些弯路而已! 首先,你必须有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什 么东西了。还是先说说我吧,我从大二的第一个学期期末的时候才开始接触单片机,但在这之前,正如上面所说的:我知道有种芯片叫单片机, 但是具体长成什么样子,却一点也不知道!看到这里很多朋友一定会忍不住发笑。嘿嘿,你可千万别笑,有些大四毕业的人也同样不知道单片 机长成什么样子呢!而我对单片机的痴迷更是常人所不能想象的地步,大二的期末考试,我全放弃了复习,每当室友拿着书在埋头复习的时候, 我却捧着自己从图书馆借的单片机书在那看,虽然有很多不懂,但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出, 或许这也是在一些三流学校的好处吧,考试挂科后,明年开学交上几十元一门的补考费,应该大部分都能过了。于是,我横下一条心,坚持看 我的单片机书和资料。 当你明白了单片机是这么一回事的时候,显而易见的问题出来了:我要选择那种语言为单片机编写程序呢?这个问题,困扰了我好久。具 体选择C51还是A51呢?汇编在我们大二之前并没有开过课,虽然看着人家的讲解,很容易明白单片机的每一时刻的具体工作情况,但是一合上 书或者资料,自己却什么也不知道了,根本不用说自己写程序了。于是,我最终还是决定学C51,毕竟C51和我们课上讲的C语言,有些类似, 编程的思想可以说是相通的。而且C51还有更大的优点就是编写大程序时的优越性更不言而喻,当然在那时,我并没有想的那么深远,C51的特 点,还是在后来的实践过程中,渐渐体会到的!朋友如果你选择了C51,那么请继续往下看,如果你选择了A51,那么你可以不要看了!因为下面讲 的全是C方面的,完全在浪费你的时间! 呵呵 ^_^ 第二,既然你想学好单片机,你必须得舍得花钱,如果不买些芯片回来自己动手焊焊拆拆的(但是在后期会介绍给大家一个很好用的硬件 仿真软件,并不需要你用实验板和仿真器了,直接在你的PC上完成,但是软件毕竟是软件,从某个特定的意义上来说是并不能代替硬件的),即使

单片机C语言变量定义定稿版

单片机C语言变量定义 HUA system office room 【HUA16H-TTMS2A-HUAS8Q8-HUAH1688】

单片机教程,51单片机C语言学习 第六课变量 上课所提到变量就是一种在程序执行过程中其值能不断变化的量。要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。定义一个变量的格式如下: [存储种类] 数据类型[存储器类型] 变量名表 在定义格式中除了数据类型和变量名表是必要的,其它都是可选项。存储种类有四种:自动(auto),外部(extern),静态(static)和寄存器(register),缺省类型为自动(auto)。这些存储种类的具体含义和用法,将在第七课《变量的存储》中进一步进行学习。 而这里的数据类型则是和我们在第四课中学习到的名种数据类型的定义是一样的。说明了一个变量的数据类型后,还可选择说明该变量的存储器类型。存储器类型的说明就是指定该变量在C51硬件系统中所使用的存储区域,并在编译时准确的定位。表6-1中是KEIL uVision2所能认别的存储器类型。注意的是在AT89C51芯片中RAM只有低128位,位于80H到FFH的高128位则在52芯片中才有用,并和特殊寄存器地址重叠。特殊寄存器(SFR)的地址表请看附录二AT89C51特殊功能寄存器列表

表6-1 存储器类型 如果省略存储器类型,系统则会按编译模式SMALL,COMPACT或LARGE所规定的默认存储器类型去指定变量的存储区域。无论什么存储模式都可以声明变量在任何的8051存储区范围,然而把最常用的命令如循环计数器和队列索引放在内部数据区可以显着的提高系统性能。还有要指出的就是变量的存储种类与存储器类型是完全无关的。

51单片机C语言程序设计复习资料

2013-2014学年上期51单片机C语言程序设计重修复习提纲考试方式:闭卷考试。 考试题型: 填空题(每空1分,共18分);单项选择题(每空2分,共18分);问答及计算题(每题4分,共16分);编程及程序阅读题(5小题,共48分)。 考试分数: 卷面成绩70%+平时成绩15%+实验成绩15%,未缺席、无课堂违纪、作业全交且认真完成的同学平时成绩可获得满分,缺席一次平时成绩扣30分,实验好评次数3次以上且实验报告全优的同学实验成绩可得满分,实验缺席一次扣30分。缺席实验和旷课共3次以上者,无考试资格。 考试时间: 18周周一(12月30日)下午14:00:16:00,考试地点:具体考室另行通知希望大家认真复习,认真听讲,不懂就问,考试成绩不及格允许查卷,如查卷卷面批阅无误成绩不做更改。 编程题为实验或实验类似的题目有3题,其余2题也取自课堂讲授例题,请务必认真复习。第一章单片机概述及单片机知识回顾 掌握什么是单片机、单片机的应用、常见单片机类型、十进制、十六进制、二进制数制转换知识。掌握单片机的硬件组成、CPU的结构、程序计数器PC的功能、存储器结构、机器周期的计算、会画出单片机的最小系统电路图及回答单片机最小系统的组成。 第二章C51语言程序设计基础(本章填空题和选择题比重较大请务必认真复习)掌握C51语言进行软件开发与汇编语言相比的优点、掌握C51的数据类型、特殊功能位的定义、C51的基本运算(位运算重点复习)、数组的定义、C51的结构及函数。 第三章AT89S51片内并行端口及编程(本章有编程题) 掌握P0-P3并行端口的特点,会开关量检测及流水灯程序的编程。 第四章AT89S51单片机的中断系统(本章有编程题) 掌握中断系统的结构、中断请求响应被满足的条件、外部中断的触发选择方式、外部中断的使用与编程。 第五章AT89S51单片机的定时器/计数器(本章有编程器) 掌握定时器的结构,TOMD及TCON的使用,定时器方式0和方式1的特点、会计算定时器初值,会用定时器中断产生PWM波形,会用定时器对外部事件进行计数。 第六章AT89S51单片机的串行口(本章有计算题) 掌握串行通信的基础知识(课本没有的内容请参照课堂讲授笔记或PPT)、串行口的四种工作方式的特点、会计算奇偶校验码、会根据波特率计算T1的初值。 第七章AT89S51单片机与输入/输出外设接口(本章有编程题) 掌握数码管动态显示的原理、掌握矩阵式键盘的原理与编程(矩阵键盘编程必考,但不会考4X4键盘)。 第八章AT89S51单片机与D/A与A/D转换器的接口(本章有编程题) 掌握AD与DA转换的接口、ADC和DAC的技术指标、常用AD和DA转换器。掌握ADC0809和TLC2543的使用与编程(2器件其中之一有编程题)。 第九章AT89S51单片机应用系统与调试(本章有编程题) 掌握单片机应用系统的软件抗干扰方法。

51单片机C语言入门教程详细解说

单片机c语言入门 相信很多爱好电子的朋友,对单片机这个词应该都不会陌生了吧。不过有些朋友可能只听说他叫单片机,他的全称是什么也许并不太清楚, 更不用说他的英文全称和简称了。单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。简称为:单片微型计算机或单片机 (Single Chip Computer)。单片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。不过这一切都没 什么关系,因为我(当然也包括任何人)都是从不知道转变成知道的,再转变成精通的。现在我只想把我学习单片机的经历,详细地讲叙给大 家听听,可能有些大虾会笑话我,想:那么简单的东西还在这里卖弄。但是你错了,我只是把我个人学习的经历讲述一遍而已,仅仅对那些想 学习单片机,但又找不到好方法或者途径的朋友,提供一个帮助,使他们在学习过程中,尽量少走些弯路而已! 首先,你必须有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什 么东西了。还是先说说我吧,我从大二的第一个学期期末的时候才开始接触单片机,但在这之前,正如上面所说的:我知道有种芯片叫单片机, 但是具体长成什么样子,却一点也不知道!看到这里很多朋友一定会忍不住发笑。嘿嘿,你可千万别笑,有些大四毕业的人也同样不知道单片 机长成什么样子呢!而我对单片机的痴迷更是常人所不能想象的地步,大二的期末考试,我全放弃了复习,每当室友拿着书在埋头复习的时候, 我却捧着自己从图书馆借的单片机书在那看,虽然有很多不懂,但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出, 或许这也是在一些三流学校的好处吧,考试挂科后,明年开学交上几十元一门的补考费,应该大部分都能过了。于是,我横下一条心,坚持看 我的单片机书和资料。 当你明白了单片机是这么一回事的时候,显而易见的问题出来了:我要选择那种语言为单片机编写程序呢?这个问题,困扰了我好久。具 体选择C51还是A51呢?汇编在我们大二之前并没有开过课,虽然看着人家的讲解,很容易明白单片机的每一时刻的具体工作情况,但是一合上 书或者资料,自己却什么也不知道了,根本不用说自己写程序了。于是,我最终还是决定学C51,毕竟C51和我们课上讲的C语言,有些类似, 编程的思想可以说是相通的。而且C51还有更大的优点就是编写大程序时的优越性更不言而喻,当然在那时,我并没有想的那么深远,C51的特 点,还是在后来的实践过程中,渐渐体会到的!朋友如果你选择了C51,那么请继续往下看,如果你选择了A51,那么你可以不要看了!因为下面讲 的全是C方面的,完全在浪费你的时间! 呵呵^_^ 第二,既然你想学好单片机,你必须得舍得花钱,如果不买些芯片回来自己动手焊焊拆拆的(但是在后期会介绍给大家一个很好用的硬件 仿真软件,并不需要你用实验板和仿真器了,直接在你的PC上完成,但是软件毕竟是软件,从某个特定的意义上来说是并不能代替硬件的),即使

合泰单片机C语言教程

Holtek 微控制器應用範例–使用Holtek C 語言目錄 第一章內容簡介 第二章選定Holtek C 語言的使用環境 2.1 進入HT-IDE3000 建立新的專案時, 選定Holtek C 編譯器 2.2 已開啟專案後, 選用Holtek C 編譯器 第三章微控制器C 語言程式的速成 3.1 定義主函式main() 3.2定義副函式(sub-function) 3.3定義全域變數(global variable) 3.4定義中斷服務函式(Interrupt Service Routine : ISR) 3.5 其他 第四章 C 語言程式 4.1 C 程式架構 4.2 開始用C 語言設計一個程式 4.2.1 定義主函式main 4.2.2 將標頭檔引入(include a header file) 4.2.3 定義文字符號及變數 4.2.4 設定微控制器及裝置的初始狀態 4.2.5 設計子函式 4.2.6 設計中斷服務函式 4.3變數(variable) 及資料型態(data type) 4.3.1 變數名 4.3.2 資料型態 4.3.3 變數的有效範圍(scope) 4.3.4 變數的資料型態(data type)

整數型(integer) 浮點型(floating point) 4.3.5 bit 資料型態 4.3.6儲存類別(storage class) 與修飾詞(qualifier) 儲存類別(storage class) 修飾詞(qualifier) 4.3.7絕對變數(absolute variable) 4.3.8常數(constant) 4.3.9指標(pointer) 與陣列(array) 指標的運算子& 與* 陣列(array) 4.3.10結構(struct) 與等位(union) 結構的運算子-> 與. 4.4運算子(Operators) 運算前的型態轉換 4.5程式流程控制(program flow control) 4.5.1if-else 敘述 4.5.2switch 敘述 4.5.3for 敘述 4.5.4while 敘述 4.5.5do-while 敘述 4.5.6goto 敘述 4.5.7break 與continue 敘述 4.6函式(Functions) 4.6.1參數(arguments) 4.6.2返回值(return values) 4.7中斷服務函式(Interrupt Service Routines) 4.8在C 語言程式中嵌入組合語言(in-line assembly code) 從組合語言的程式去存取 C 語言的物件(變數) 4.9前置處理指令(Preprocessor) 4.9.1 定義文字符號(#define)

51单片机声控智能小车C语言程序设计代码

51单片机声控智能小车C语言程序设计代码 #include #define uint unsigned int #define uchar unsigned char unsigned char code LEDShowData[]={0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x19,0x03}; sbit LED=P0^7; sbit m1a=P0^0; sbit m1b=P0^1; sbit m2a=P0^2; sbit m2b=P0^3; sbit B1=P0^4; uint m,n,x,y,z; void delayB1() { unsigned int delaytime=500; while(delaytime--); return; } void delayLED(uint ms) { uint a,b; for(a=0;a

TR0=1;//启动T0定时器 TR1=0;//关闭T1定时器 m1a=1; m2a=1; } void timer2(void) interrupt 5 { TF2=0;//软件对T2标志位清零 n++; if(n==250)//n控制查询周期时间 { n=0; switch(m) { case 1://低速挡,占空比77.8% { P2=LEDShowData[0];//七段数码管显示1 TH0=210; TL0=210;//对T0定时器赋初值 TH1=240; TL1=240;//对T1定时器赋初值 x=m; m=0; z=0; ET0=1; ET1=1; TR0=1;//启动T0定时器 break;//跳出switch } case 2://高速挡,占空比99.6% { P2=LEDShowData[1];//七段数码管显示2 TH0=1; TL0=1; //对T0定时器赋初值 TH1=255; TL1=255; //对T1定时器赋初值 x=m+1; m=0; z=0; ET0=1; ET1=1; TR0=1; //启动T0定时器 break;//跳出switch }

单片机C语言项目式教程课后题解大学期末复习资料

思考与讨论题 1-1什么是单片机?它与一般微型计算机在结构上何区别? 答: 单片微型计算机简称为单片机(Single Chip Computer),又称为微控制器(MCU即Micro-Controller Unit)。它是在一块芯片上集成了中央处理器(CPU)、存储器(RAM、ROM)、定时器/计数器、中断控制、各种输入/输出(I/O)接口(如并行I/O口、串行I/O口和A/D转换器)等为一体的器件。 微型计算机的基本结构由CPU(运算器、控制器)、存储器、输入设备和输出设备五大部分组成,各部分通过外部总线连接而成为一体。 单片机的结构是在一块芯片上集成了中央处理器(CPU)、存储器、定时器/计数器、中断控制、各种输入/输出接口(如并行I/O口、串行I/O口和A/D转换器)等,它们通过单片机内部部总线连接而成为一体。 1-2 单片机的发展大致可分为几个阶段?各阶段的单片机功能特点是什么?

答: 1976年9月Intel公司推出MCS-48单片机,8位机 1978年下半年Motorola公司推出M6800系列单片机,增加了串口功能 1982年Mostek公司和Intel公司先后又推出了性能更高的16位机 思考与讨论题 2-1 串行在线仿真系统中单片机与PC机的通信线怎样连接? 答: 设计好单片机产品硬件,作一根通信线,一般是买一根标准串口通信线,一端(A端)9芯插头与PC机相连,另一端(B 端)的插头不用,直接将三根线分别与单片机的串口和地相连(A端的2脚与单片机的P3.0连;A端的3脚与单片机的P3.1连;A端的5脚与单片机的地连;A端的7脚与A端的8脚短接;A端的4脚与A端的6脚短接)。 2-2 在线仿真与软件仿真的主要区别在哪里?

!单片机C语言简明教程

本文由xianguogao贡献 ppt文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 C语言程序设计 语言程序设计 1.0 1.1 1.2 1.3 为什么要学习C语言? § 计算机学的许多知识都具有相通性,因 而,不断追赶时髦技术而忽略基本功的 做法是徒劳无意的.我们最多需要"精 通 "三种语言,最佳拍档是汇编,C, C++(或JAVA),很显然,如果你"精 通"了这三种语言,其它语言你应该是 可以很快"熟悉"的,否则你就没有 "精通 "它们. § C语言是嵌入式开发的主要语言 1.0 1.1 1.2 1.3 初级入门教材 1. 《C程序设计语言》(The C Programming Language,第2版 新版) Brain W. Kernighan 和 Dennis.M.Ritchie 著 2. 《C Primer Plus(第五版)中文版》 Stephen Prata著,云巅工作室 译 3. 《C和指针》(Pointers on C) (美)Kenneth A. Reek著 徐波译 4. 《C语言程序设计》 谭浩强 著 清华大学出版社 1.0 1.1 1.2 1.3 C语言进阶书籍 《C陷阱与缺陷》(C Traps and Pitfalls)Andrew Koenig 著 《C专家编程》 (美) Peter Van Der Linden著 徐波译 《C语言编程常见问题解答》(C Programming : Just the Faqs ) Paul S.R. Chisholm 等著 《C/C++嵌入式系统编程》(Programming Embedded Systems in C and C++) 作者:Michael Barr 《高质量程序设计指南:C++/C语言 》林锐, 韩永 泉编著 把这几本书吃透,足 以使你成为C语言高手 了 西电本科硕士,浙大博士, 著名网文:大学十年 购书方法 §互动出版社(china-pub) §网址:www.china-pub.com §好处: 搜索同类型书,版本全面,经常会有意外收获 有购书网友的心得,评论,可未读先知 有一定价格优惠 信誉较好,可靠 上机调试方法 1. IAR C编译器 EW430 3.41A软件 2. Dev C++软件 Dev-C++ 是一个 C++ 开发工具.它包括多页面窗 口,工程编辑器,在工程编辑器中集合了编辑 器,编译器,连接程序和执行程序.它也提供 高亮度语法显示的,以减少编辑错误. 一些重要的学习论坛 1. 2. 3. 4. 5. http://www.mcu-china.com/ 南航魏小龙主页 http://www.microcontrol.cn/bbs/Boards.asp

51单片机C语言变量定义

单片机教程,51单片机C语言学习 第六课变量 上课所提到变量就是一种在程序执行过程中其值能不断变化的量。要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。定义一个变量的格式如下:[存储种类]数据类型[存储器类型]变量名表 在定义格式中除了数据类型和变量名表是必要的,其它都是可选项。存储种类有四种:自动(auto),外部(extern),静态(static)和寄存器(register),缺省类型为自动(auto)。这些存储种类的具体含义和用法,将在第七课《变量的存储》中进一步进行学习。 而这里的数据类型则是和我们在第四课中学习到的名种数据类型的定义是一样的。说明了一个变量的数据类型后,还可选择说明该变量的存储器类型。存储器类型的说明就是指定该变量在C51硬件系统中所使用的存储区域,并在编译时准确的定位。表6-1中是KEIL uVision2所能认别的存储器类型。注意的是在AT89C51芯片中RAM只有低128位,位于80H到FFH的高128位则在52芯片中才有用,并和特殊寄存器地址重叠。特殊寄存器(SFR)的地址表请看附录二 如果省略存储器类型,系统则会按编译模式SMALL,COMPACT或LARGE所规定的默认存储器类型去指定变量的存储区域。无论什么存储模式都可以声明变量在任何的8051存储区范围,然而把最常用的命令如循环计数器和队列索引放在内部数据区可以显著的提高系统性能。还有要指出的就是变量的存储种类与存储器类型是完全无关的。 SMALL存储模式把所有函数变量和局部数据段放在8051系统的内部数据存储区这使访问数据非常快,但SMALL存储模式的地址空间受限。在写小型的应用程序时,变量和数据放在data内部数据存储器中是很好的因为访问速度快,但在较大的应用程序中data区最好只存放小的变量、数据或常用的变量(如循环计数、数据索引),而大的数据则放置在别的存储区域。 COMPACT存储模式中所有的函数和程序变量和局部数据段定位在8051系统的外部数据存储区。外部数据存储区可有最多256字节(一页),在本模式中外部数据存储区的短地址用@R0/R1。 LARGE存储模式所有函数和过程的变量和局部数据段都定位在8051系统的外部数据区外部数据区最多可有64KB,这要求用DPTR数据指针访问数据。 之前提到简单提到sfr,sfr16,sbit定义变量的方法,下面我们再来仔细看看。

单片机C语言变量定义

单片机C语言变量定义 Company number【1089WT-1898YT-1W8CB-9UUT-92108】

单片机教程,51单片机C语言学习 第六课变量 上课所提到变量就是一种在程序执行过程中其值能不断变化的量。要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间。定义一个变量的格式如下: [存储种类] 数据类型[存储器类型] 变量名表在定义格式中除了数据类型和变量名表是必要的,其它都是可选项。存储种类有四种:自动(auto),外部(extern),静态(static)和寄存器(register),缺省类型为自动(auto)。这些存储种类的具体含义和用法,将在第七课《变量的存储》中进一步进行学习。 而这里的数据类型则是和我们在第四课中学习到的名种数据类型的定义是一样的。说明了一个变量的数据类型后,还可选择说明该变量的存储器类型。存储器类型的说明就是指定该变量在C51硬件系统中所使用的存储区域,并在编译时准确的定位。表6-1中是KEILuVision2所能认别的存储器类型。注意的是在AT89C51芯片中RAM只有低128位,位于80H到FFH的高128位则在52芯片中才有用,并和特殊寄存器地址重叠。特殊寄存器(SFR)的地址表请看附录二AT89C51特殊功能寄存器列表

表6-1 存储器类型 如果省略存储器类型,系统则会按编译模式SMALL,COMPACT或LARGE 所规定的默认存储器类型去指定变量的存储区域。无论什么存储模式都可以声明变量在任何的8051存储区范围,然而把最常用的命令如循环计数器和队列索引放在内部数据区可以显着的提高系统性能。还有要指出的就是变量的存储种类与存储器类型是完全无关的。 SMALL存储模式把所有函数变量和局部数据段放在8051系统的内部数据存储区这使访问数据非常快,但SMALL存储模式的地址空间受限。在写小型的应用程序时,变量和数据放在data内部数据存储器中是很好的因为访问速度快,但在较大的应用程序中data区最好只存放小的变量、数据或常用的变量(如循环计数、数据索引),而大的数据则放置在别的存储区域。 COMPACT存储模式中所有的函数和程序变量和局部数据段定位在8051系统的外部数据存储区。外部数据存储区可有最多256字节(一页),在本模式中外部数据存储区的短地址用@R0/R1。 LARGE存储模式所有函数和过程的变量和局部数据段都定位在8051系统的外部数据区外部数据区最多可有64KB,这要求用DPTR数据指针访问数据。

51单片机及C语言入门教程

51单片机 及C语言入门教程 注:排成16开版式,是为了方便自已打印阅读。请不要用于非法用途。 2007.12.20

51单片机及C语言入门教程 第一课 建立您的第一个C项目 使用C语言肯定要使用到C编译器,以便把写好的C程序编译为机器码,这样单片机才能执行编写好的程序。KEIL uVISION2是众多单片机应用开发软件中优秀的软件之一,它支持众多不同公司的MCS51架构的芯片,它集编辑,编译,仿真等于一体,同时还支持,PLM,汇编和C语言的程序设计,它的界面和常用的微软VC++的界面相似,界面友好,易学易用,在调试程序,软件仿真方面也有很强大的功能。因此很多开发51应用的工程师或普通的单片机爱好者,都对它十分喜欢。 以上简单介绍了KEIL51软件,要使用KEIL51软件,必需先要安装它。KEIL51是一个商业的软件,对于我们这些普通爱好者可以到KEIL中国代理周立功公司的网站上下载一份能编译2K的DEMO版软件,基本可以满足一般的个人学习和小型应用的开发。(安装的方法和普通软件相当这里就不做介绍了) 安装好后,你是不是迫不及待的想建立自己的第一个C程序项目呢?下面就让我们一起来建立一个小程序项目吧。或许你手中还没有一块实验板,甚至没有一块单片机,不过没有关系我们可以通过KEIL软件仿真看到程序运行的结果。 首先当然是运行KEIL51软件。怎么打开?噢,天!那你要从头学电脑了。呵呵,开个玩笑,这个问题我想读者们也不会提的了:P。运行几秒后,出现如图1-1的屏幕。 图1-1启动时的屏幕

接着按下面的步骤建立您的第一个项目: (1)点击Project菜单,选择弹出的下拉式菜单中的New Project,如图1-2。接着弹出一个标准Windows文件对话窗口,如图1-3,这个东东想必大家是见了N次的了,用法技巧也不是这里要说的,以后的章节中出现类似情况将不再说明。在"文件名"中输入您的第一个C程序项目名称,这里我们用"test",这是笔者惯用的名称,大家不必照搬就是了,只要符合Windows文件规则的文件名都行。"保存"后的文件扩展名为uv2,这是KEIL uVision2项目文件扩展名,以后我们可以直接点击此文件以打开先前做的项目。 图1-2New Project菜单 图1-3文件窗口 (2)选择所要的单片机,这里我们选择常用的Ateml公司的AT89C51。此时屏幕如图1-4

新概念51单片机C语言教程例题

目录 例编写程序,点亮第一个发光二极管(P27 )错误!未定义书签。例利用for 语句延时特性,编写第一个发光二极管以间隔1S 亮灭闪动的程序(P42 )错误!未定义书签。 例编写程序使第一个发光二极管以间隔500ms亮灭闪动。(P48 )错误!未定义 书签。 例编写程序使第一个二极管以亮200ms灭800ms的方式闪动。P49)错误味定义书签。 例利用C51自带库_crol_(),以间隔500ms实现流水灯程序(P53)错误味定义书签。 例编写程序使第一个数码管显示8(P59 )....... 错误!未定义书签。 例让实验板上6个数码管同时点亮,依次显示0到F,时间间隔为,循环下去。 (P61 )..................... 错误!未定义书签。 例第一个数码管显示 1 ,时间为,然后关闭它,立即让第二个数码管显示2,时间为,在关闭它……一直到最后一个数码管显示6,时间同样为,关闭它之后再 回来显示第一个数码管,一直循环下去。(P62 ) ... 错误!未定义书签。 例利用定时器0 工作方式1,在实验板上实现第一个发光管以1s 亮灭闪烁。 (P74 )..................... 错误!未定义书签。 例用定时器0的方式1实现个第一发光二极管以200ms间隔闪烁,用定时器1 的方式 1 实现数码管前两位59s 循环计时。(P75 )错误!未定义书签。例用数码管前两位显示一个十进制数,变化范围为00~59,开始时显示00,每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零;按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下

单片机C语言项目式教程综合题含答案

百度文库 六、综合题 1.现有8031单片机、74LS373锁存器、1片2764EPROM和2片6116RAM,请使用他们组成一个单片机系统,要求: (1)画出硬件电路连线图,并标注主要引脚; (2)指出该应用系统程序存储器空间和数据存储器空间各自的地址范围。 解:(1)电路图如下所示: (2)2764的地址为C000H-DFFFH; 第一个6116的地址为A000H-A7FFH; 第二个6116的地址为6000H-67FFH; 事实上,由于采用的是线选法,导致了地址不连续,地址空间利用不充分。建议在实际工作中要具体情况具体分析。在两种地址分配中选一种较好的来应用。

U 4 74L S 373 347813141718 1 11 256912151619 D 0D 1D 2D 3D 4D 5D 6D 7O C G Q 0Q 1Q 2Q 3Q 4Q 5Q 6Q 7 U 2 8031 31 393837363534333221 2223242526272817162930 E A /V P P 0.0 P 0.1P 0.2P 0.3P 0.4P 0.5P 0.6P 0.7P 2.0 P 2.1P 2.2P 2.3P 2.4P 2.5P 2.6P 2.7R D W R P S E N A L E /P U 5 H M 6116 876543212322191820219 10111314151617A 0A 1A 2A 3A 4A 5A 6A 7A 8A 9A 10C S O E W E D 0D 1D 2D 3D 4D 5D 6D 7U 3 2764 109876543252421232202227111 12131516171819A 0A 1A 2A 3A 4A 5A 6A 7A 8A 9A 10A 11A 12C E O E P G M V P P O 0 O 1O 2O 3O 4O 5O 6O 7U 6 H M 6116 876543212322191820219 10111314151617A 0A 1A 2A 3A 4A 5A 6A 7A 8A 9A 10C S O E W E D 0 D 1D 2D 3D 4D 5D 6D 7

C语言作单片机初级教程

C语言作单片机初级教 程

51单片机C语言学习杂记 学习单片机实在不是件易事,一来要购买高价格的编程器,仿真器,二来要学习编程语言,还有众多种类的单片机选择真是件让人头痛的事。在众多单片机中51 架构的芯片风行很久,学习资料也相对很多,是初学的较好的选择之一。51 的编程语言常用的有二种,一种是汇编语言,一种是C 语言。汇编语言的机器代码生成效率很高但可读性却并不强,复杂一点的程序就更是难读懂,而C 语言在大多数情况下其机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,而且C 语言还可以嵌入汇编来解决高时效性的代码编写问题。对于开发周期来说,中大型的软件编写用C 语言的开发周期通常要小于汇编语言很多。综合以上C 语言的优点,我在学习时选择了C 语言。以后的教程也只是我在学习过程中的一些学习笔记和随笔,在这里加以整理和修改,希望和大家一起分享,一起交流,一起学习,一起进步。 *注:可以肯定的说这个教程只是为初学或入门者准备的,笔者本人也只是菜鸟一只,有望各位大侠高手指点错误提出建议。 明浩2003-3-30 第一课建立您的第一个C项目 使用C 语言肯定要使用到C 编译器,以便把写好的C 程序编译为机器码,这样单片机才能执行编写好的程序。KEIL uVISION2 是众多单片机应用开发软件中优秀的软件之一, 它支持众多不同公司的MCS51 架构的芯片,它集编辑,编译,仿真等于一体,同时还支持,PLM,汇编和C 语言的程序设计,它的界面和常用的微软VC++的界面相似,界面友好,易 学易用,在调试程序,软件仿真方面也有很强大的功能。因此很多开发51 应用的工程师或普通的单片机爱好者,都对它十分喜欢。 以上简单介绍了KEIL51 软件,要使用KEIL51 软件,必需先要安装它。KEIL51 是一个 商业的软件,对于我们这些普通爱好者可以到KEIL 中国代理周立功公司的网站上下载一份能编译2K 的DEMO 版软件,基本可以满足一般的个人学习和小型应用的开发。(安装的方 法和普通软件相当这里就不做介绍了) 安装好后,您是不是迫不及待的想建立自己的第一个C 程序项目呢下面就让我们一 起来建立一个小程序项目吧。或许您手中还没有一块实验板,甚至没有一块单片机,不过没有关系我们可以通过KEIL 软件仿真看到程序运行的结果。 首先当然是运行KEIL51 软件。怎么打开噢,天!那您要从头学电脑了。呵呵,开个 玩笑,这个问题我想读者们也不会提的了:P。运行几秒后,出现如图1-1 的屏幕。 图1-1 启动时的屏幕

单片机c语言教程

第一课建立你的第一个KeilC51项目 随着单片机技术的不断发展,以单片机C语言为主流的高级语言也不断被更多的单片机爱好者和工程师所喜爱。使用C51肯定要使用到编译器,以便把写好的C程序编译为机器码,这样单片机才能执行编写好的程序。KEIL uVISION2 是众多单片机应用开发软件中优秀的软件之一,它支持众多不一样公司的MCS51架构的芯片,它集编辑,编译,仿真等于一体,同时还支持,PLM,汇编和C 语言的程序设计,它的界面和常用的微软 VC++的界面相似,界面友好,易学易用,在调试程序,软件仿真方面也有很强大的功能。本站提供的单片机c语言教程都是基于keilc51的。 下面结合8051介绍单片机C语言的优越性: ·无须懂得单片机的具体硬件,也能够编出符合硬件实际的专业水平的程序; ·不懂得单片机的指令集,也能够编写完美的单片机程序; ·不同函数的数据实行覆盖,有效利用片上有限的RAM空间; ·提供auto、static、const等存储类型和专门针对8051单片机的data、idata、pdata、xdata、code等存储类型,自动为变量合理地分配地址; ·C语言提供复杂的数据类型(数组、结构、联合、枚举、指针等),极大地增强了程序处理能力和灵活性; ·提供small、compact、large等编译模式,以适应片上存储器的大小; ·中断服务程序的现场保护和恢复,中断向量表的填写,是直接与单片机相关的,都由C编译器代办; ·程序具有坚固性:数据被破坏是导致程序运行异常的重要因素。C语言对数据进行了许多专业性的处理,避免了运行中间非异步的破坏 ·提供常用的标准函数库,以供用户直接使用; ·有严格的句法检查,错误很少,可容易地在高级语言的水平上迅速地被排掉; ·可方便地接受多种实用程序的服务:如片上资源的初始化有专门的实用程序自动生成;再如,有实时多任务操作系统可调度多道任务,简化用户编程,提高运行的安全性等等。 ·头文件中定义宏、说明复杂数据类型和函数原型,有利于程序的移植和支持单片机的系列化产品的开发; 以上简单介绍了 KEILC51 软件,要使用KEILC51软件,必需先要安装它,这也是学习单片机编程语言所要求的第一步――建立学习环境。 本站提供无限制版的keil c51下载(此处)(安装的方法在压缩包内有详细说明,这里就不做介绍了)

单片机C语言项目式教程课程标准

一、课程基本情况 课程名称单片机原理与应用 授课对象 系电子工程系 专业05微电、应电、计控 学分 4 总学时64 讲课学时52 实验学时12 选修要求必修 教材名称、作者、出版社及版次 《单片机C语言项目式教程》龚运新北京邮电大学出版社第一版 实验指导书名称、作者、出版社及版次 单片机实验、实训指导书无锡科技职业学院电子工程系 参考书名称、作者、 出版社及版次 单片机教程张迎新北京航空航天出版社第一版 二、课程的性质和任务 1、课程性质 《单片机C语言项目式教程》是应用电子专业、智能控制专业、自动化专业、电气控制专业、机电一体化专业、智能仪表专业等专业(本科、高职高专) 的一门专业课程。 2、课程任务 通过学习本课程,能了解单片机一般应用技术,初步掌握用汇编语言设计程序的有关基本知识和程序设计的能力,能用进行产品开发。

三、教学目标 1、知识目标 1)掌握:要求学生能够全面、深入理解和熟练掌握所学内容,并能够用其分析、初步设计和解答与应用相关的问题,能够举一反三 2)理解:要求学生能够较好地理解所学内容,并且能够进行简单分析和判断3)了解:要求学生能够一般地知道所学内容 2、能力目标 1)通过对单片机CPU和各接口部件的组成、原理、程序设计的学习及实验,建立完备的产品整机概念 2)通过使用汇编语言编程控制,实现各种功能,了解所用各种接口及软件编程方法,并为后继课程及今后工作中解决实际问题,打下一个良好的基础3)通过实验课的学习,使学生受到软硬件实验的初步训练,实验操作能力得到提高。掌握编程的基本方法,培养分析和解决问题的能力,以及掌握使用计算机的基本技能 四、教学内容和基本要求(以提纲式列出说明) 项目一单片机识别与展望 1、课程教学基本要求 1) 了解单片机的基本知识 2) 了解单片机的发展与未来 3) 掌握单片机系统的应用 2、教学重点

51单片机C语言程序设计经典案例

项目三C51程序设计语言基础 任务1 C51程序的识读 1.C51程序结构 例3-1 P_test /********************* //注释,还可用//注释掉一行 File name:P_test.c Chip name:STC89C51RC Clock frequency:1.20MHz ***********************/ #include “reg52.h”//预处理命令,文件包含预处理命令,后缀名都是.h,标准的MCS-51单片机头文件为”reg51.h”,STC89系列单片机头文件为”reg52.h” #define unit unsigned int //宏定义预处理命令 sbit BZ=P3`7 ; sbit key=P1`0; void delay(unit ms) { unit i; while( ms --) { for(i=0;i<120;i++); } } void main(void) { while(1) { if(key==0) { BZ=0x0; delayms(10); BZ=0x1; delayms(50); P0=0xFF; } else { P0=~P0; delayms(500); } } } 2.C51的数据类型

位变量型bit 字符型无符号字符型unsigned char 有符号字符型signed char C51的数据类型整数型无符号整数型unsigned int 基本类型有符号整数型signed int 长整数型无符号长整数型unsigned long int 有符号长整数型signed long int 实数型(浮点型)单精度浮点型float 双精度浮点型double 数组类型array 结构体类型struct 构造类型共用体union 枚举enum 指针类型 空类型(void) 表3-1 C51基本数据类型的长度和值域 类型长度/bit 长度/byte 范围 位变量型bit 1 0 ,1 无符号字符型unsigned char 8 单字节0-255 有符号字符型signed char 8 单字节-128-127 无符号整数型unsigned int 16 双字节0-65536 有符号整数型signed int 16 双字节-32768-32767 无符号长整数型unsigned long int 32 四字节 有符号长整数型signed long int 32 四字节 单精度浮点型float 32 四字节 双精度浮点型double 32 四字节 一般指针类型24 三字节 3.C51的标识符和关键字 标识符是由字母、数字和下划线组成的字符串,第一个字符必须是字母或下划线,不超过32个字符。 表3-2 C51中的关键字 关键字用途说明 auto 存储种类声明用来声明局部变量 bdata 存储器类型说明可位寻址的内部数据存储器 break 程序语句退出最内层循环体 bit 位变量语句位变量的值是1(true)或0(flase)case 程序语句switch语句中的选择项 char 数据类型的声明单字节整数型或字符型数据

1小时学会51单片机C语言入门教程

1小时学会51单片机C语言入门教程相信很多爱好电子的朋友,对单片机这个词应该都不会陌生了吧。不过有些朋友可能只听说他叫单片机,他的全称是什么也许并不太清楚,更不用说他的英文全称和简称了。单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。简称为:单片微型计算机或单片机 (Single Chip Computer)。单片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。不过这一切都没什么关系,因为我(当然也包括任何人)都是从不知道转变成知道的,再转变成精通的。现在我只想把我学习单片机的经历,详细地讲叙给大家听听,可能有些大虾会笑话我,想:那么简单的东西还在这里卖弄。但是你错了,我只是把我个人学习的经历讲述一遍而已,仅仅对那些想学习单片机,但又找不到好方法或者途径的朋友,提供一个帮助,使他们在学习过程中,尽量少走些弯路而已~ 首先,你必须有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什么东西了。还是先说说我吧,我从大二的第一个学期期末的时候才开始接触单片机,但在这之前,正如上面所说的:我知道有种芯片叫单片机,但是具体长成什么样子,却一点也不知道~看到这里很多朋友一定会忍不住发笑。嘿嘿,你可千万别笑,有些大机长成什么样子呢~而我对单片机的痴迷更是常四毕业的人也同样不知道单片人所不能想象的地步,大二的期末考试,我全放弃了复习,每当室友拿着书在埋头复习的时候,我却捧着自己从图书馆借的单片机书在那看,虽然有很多不懂, 或但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出,许这也是在一些三流学校的好处吧,考试挂科后,明年开学交上几十元一门

相关主题
文本预览
相关文档 最新文档