单片机的C语言程序设计与应用基于Proteus仿真第2版Word格式.docx
- 文档编号:18964775
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:21
- 大小:22.10KB
单片机的C语言程序设计与应用基于Proteus仿真第2版Word格式.docx
《单片机的C语言程序设计与应用基于Proteus仿真第2版Word格式.docx》由会员分享,可在线阅读,更多相关《单片机的C语言程序设计与应用基于Proteus仿真第2版Word格式.docx(21页珍藏版)》请在冰豆网上搜索。
//访问定时器0,设置时间常数
TH0=ox3c;
TR0=1;
//启动定时器0
…
3-3sbit型变量的定义示例
程序如下:
sfrPSW=0xD0;
sbitOV=PSW^2;
sbitOV=0xd0^2;
sbitOV=0xD2;
unsignedcharbdataflag;
sbitflag0=flag^0;
sfrp1=0x90;
sbitp1_0=p1^0;
sbitp1_1=p1^1;
sbitp1_2=p1^2;
sbitp1_3=p1^3;
sbitp1_4=p1^4;
sbitp1_5=p1^5;
sbitp1_6=p1^6;
sbitp1_7=p1^7;
3-4片内I/O口及其位的定义示例。
sfrP1=0x90;
//P1口的SFR定义
sfrP3=0xB0;
//P3口的SFR定义
sbitDIPswitch=P1^4;
//P3口的4位DIP开关输入
sbitgreenLED=P1^5;
//P1口的5位的绿LED输出
{unsignedchardatainval;
inval=0;
//inval的初始化值
while
(1)
{P1=0XFF;
{inval=p1&
0x0f;
//从P1读位0~3
}
}
3-5片内RAM、片外RAM及I/O的定义示例
absacc.h>
#definePAXBYTE[0xffec]//将PA定义为外部I/O口,地址为0xffec
#defineNRAMDBYTE[0x40]/*将NRAM定义为片内RAM,地址为40H,长度为8位*/
{PA=0x3A;
//将数据3AH写入地址0xffec的外部I/O端口
NRAM=0x01;
//将数据01H写入片内RAM40H单元
3-6通过_at_实现绝对地址的访问示例。
dataunsignedcharx1_at_0x40;
/*在data区定义字节变量x1,它的地址为40H*/
xdataunsignedintx2_at_0x2000;
/*在xdata区定义字符变量x2,它的地址为2000H*/
{x1=0xff;
x2=0x1234;
while
(1);
3-7将片外RAM6000H开始的连续的10个字节单元内容清0.
xdataunsignedcharBuffer[10]_at_0x6000;
voidmain(void)
{unsignedcharindex;
for(index=0;
index<
10;
index++)
{Buffer[index=0]
如果是片内RAM60H单元开始的10个单元内容清0,可以这样编程:
dataunsignedcharBuffer[10]_at_0x60;
3-8自增和自减运算符的程序示例
voidmain()
{intx,y,z1,z2;
x=10;
y=21;
z1=(x++)+(x++);
printf("
x=%d,z1=%d\n"
x,z1);
z2=(++y)+(++y);
y=%d,z2=%d\n"
y,z2);
执行结果如下:
x=12,z1=21
y=23,z2=45
3-9关系运算符运算的程序示例
{inta,b,c,d;
a=-2.3>
0;
b=71==32;
c=7!
=0;
d=-12<
a=%d,b=%d,c=%d,d=%d\n"
a,b,c,d);
a=0,b=0,c=1,d=1
3-10逻辑运算的程序示例
{inta,b,c,d,e;
a=!
0;
b=15&
&
22;
c=35&
d=17.3||0;
e=17.3||2.6;
a=%d,b=%d,c=%d,d=%d,e=%d\n"
a,b,c,d,e);
a=1,b=1,c=0,d=1,e=1
3-11利用位移运算符进行循环移位的示例。
若a=11000011B,将a值右循环位移2位。
a右循环n位,即将a中原来左面(8-n)位右移n位,而将原来右端的n位移到最左面的n位。
上述问题可以由下列步骤来实现。
1.将a的右端n位先放到b中的高n位中:
b=a<
<
(8-n)
2.将a右移n位,其左面高n位被补0:
c=a>
>
n
3.将b、c进行或运算:
a=c|b
对a进行循环右移两位的程序如下:
main()
{unsignedchara=0xc3,b,c;
intn=2;
b=a<
(8-n);
n;
a=c|b;
结果如下:
循环右移前a=11000011B
循环右移后a=11110000B
3-12位运算程序示例
{inta,b,c;
a=23;
b217;
c=a&
b;
a&
b=%d\n"
c);
c=a|b;
a|b=%d\n"
c=a^b;
a^b=%d\n"
c=~a;
~a=%d\n"
c=a<
3;
a<
3=%d\n"
c=b>
2;
b>
b=17
a|b=223
a^b=206
~a=-24
3=184
2=54
3-13分支编程示例
有一个函数如下:
1x>
y=0x=0
-1x<
编写一个程序,输入一个x值,输出y值。
使用嵌套的if语句判断函数y的取值。
#include<
main()
{intx,y;
scanf()
if(x<
0)y=-1;
else
{if(x==0)y=0;
elsey=1;
x=%d,y=%d\n"
x,y);
3-14选择语句程序示例
{inta,b;
a=200;
b=321;
if(a==b)
{a++;
b++;
a=%d,b=%d\n"
a,b);
a=200,b=321
3-15选择语句程序示例
a=12;
b=21;
{a--;
b--;
a=11,b=20
3-16选择语句程序示例
{intscore;
chargrade;
score=45;
if(score>
=90)
grade='
A'
;
elseif(score>
=80)
B'
=70)
C'
=60)
D'
elsegrade='
E'
score=%d,grade=%c\n"
score,grade);
score=45,grade=E
3-17Proteus仿真电路如图所示。
AT89C51单片机的P1.0和P1.1引脚接有两只按键,其4种逻辑组合分别点亮由P2.0~P2.3控制的4只LED(低电平点亮),试编程实现此功能。
参考程序如下:
{chara;
do
{P1=0xff;
a=p1;
a=a&
0x03;
switch(a)
{case0:
P2=0x0e;
break;
case1:
P2=0x0d;
case2:
P2=0x0b;
case3:
P2=0x07;
}while
(1);
3-18实型数组sample存有10个采样值,编写一个函数返回其平均值(即平均值滤波程序)
floatavg(float*sample)
{floatsum=0;
charno=0;
{sum+=sample[no];
no++;
}while(no<
10);
return(sum/10)
3-19时间延迟程序举例
循环的基本用途之一是用嵌套产生时间延迟,执行的指令消磨一定已知的时间。
这种延时方法是依靠一定数量的时钟周期来计时的,
所以延时依赖于晶振频率。
8051单片机的数据手册中列出了每一条机器指令所需要的时钟周期数,使用2MHzDE晶振,12个震荡指令花费1μs
下面是一个延时1ms的延时程序。
如果给这个程序传递一个50的数值,则可产生约50ms的延时。
voidmsec(unsignesintx)
{unsignedcharj;
while(x--)
{for(j=0;
j<
125;
j++)
{;
根据汇编代码进行的分析表明,用j进行的内部循环大约延时8μs
3-20[break语句]无符号char型数据sdata内存放一个随机数,这个数据每秒产生一次,要求计算这些数据的和,当和超过4000时不再计算,并且计算花费的时间。
{unsignedcharsdata;
inttime;
//存放和花费的秒数
doublesum;
//和
sum=0;
time=0;
sdata=0;
for(;
)
{time++;
//计算秒数
sum=sum+sdata;
//计算和
if(sum>
4000)
{break;
//退出整个循环
}由于不知道什么时候能够超过4000,所以使用一个‘无限循环’,每次计算和之后判断当前sum的值,当sum超过4000时使用break退出整个循环,不再执行。
3-21[continue语句]退出当前循环,不再执行本轮循环,从下一轮循环开始执行。
无符号char型数据sdata内存放一个随机数,这个数据每秒产生一次,如果这个数据不等于0x45,则计算这些数据的和,当和超过4000时停止计算,
保存出现的0x45的个数并且计算整个过程花费的时间。
intcounter;
counter=0;
//计算秒和
if(sdata==0x45)//如果等于0x45
{counter++;
//统计出现的个数
continue;
//退出本次循环,不计算sum
else//如果不等于0x45
{sum=sum+sdata;
}当sdata等于0x45时,利用continue语句退出本次循环;
当sum和大于4000时,使用break语句退出整个循环。
3-22[goto语句]无条件转移语句
计算1~100的和,存放到sum中
{unsignedcharcounter;
intsum;
sumadd:
sum=sum+counter;
counter++;
if(counter<
101)
{gotosumadd;
3-23一维数组程序示例
如图所示为一由MCS-51单片机控制指示灯的proteus仿真电路,此电路从P0口相连的8个开关读入空置量信息,将最近读入的10次信息存储在10字节数组
chararray[10]中,并把读入的信息显示在与P2口相连接的8位LED指示灯上。
每次读入显示信息间隔100ms,由延时程序msec(100)完成。
相应的C语言程序流程图如下
voidmsec(unsignedint);
{unsignedchararray[10];
unsignedchari;
{for(i=0;
i<
=9;
i++)
{array[i]=p2=p0;
msec(100);
voidmsec(unsignedintx);
while((x--)!
=0)
{for(j=0;
{;
3-24将摄氏温度转换成华氏温度
#defineucharunsignedchar
ucharcodetempt[]={32,34,36,37,39,41};
/*数组,设置在EPROM中,长度为实际输入的数值数*/
ucharftoc(uchardegc)
{returntempt[degc]/*返回华氏温度值*/
{ucharx;
x=ftoc(5);
/*得到与5℃相应的华氏温度值*/
3-25利用指针变量完成A/D接口的启动和读取结果值。
unsignedcharxdata*ADC;
/*定义ADC0809的端口指针*/
unsignedcharxdata*ADCdata;
/*定义ADC0809数据缓冲器指针*/
unsignedchari;
{ADC=0x00f0;
ADCdata=0x1000;
/*定义地址端口和数据缓冲器地址*/
i=8;
/*ADC0809有8个模拟输入通道*/
EA=1;
EX1=1;
IT1=1;
/*开中断*/
*ADC=i;
/*启动ADC0809*/
while(i);
/*等待8个通道转换结束*/
voidint1()interrupt2
{unsignedchartmp;
tmp=*ADC;
*ADCdata=tmp;
/*读出A/D转换结果*/
ADCdata++;
/*数据存到数据缓冲器*/
i--;
/*启动下一个模拟输入通道A/D转换*/
3-26无参函数举例。
程序如下
func()
(printf("
FunctionInfuncrespondthecallofMain\n"
);
{printf("
FunctionInMainCallsAFunctioninfunc\n"
func();
上面的程序中,实际上定义了两个函数main()和func()。
它们都是无参函数,因此它们的返回值类型标识符可以省略,默认值是int类型。
3-27求两个数的最大公约数程序如下
intgcd(u,v)
intu,v;
{inttemp;
while(v!
{temp=u%v;
u=v;
v=temp;
return(u);
{intresult,a=150,b=35;
SCON=0x50;
TM0D=0x20;
TH1=0xf3;
TR1=1;
T1=1;
result=gcd(a,b);
Thegcdof%dand%dis%d\n"
a,b,result);
程序运行结果为a=150b=35
Thegcdof150and35is5
3-28中断函数举例程序如下
unsignedintinterruprcnt;
unsignedcharsecond;
voidtimer0(void)interrupt1using2
{if(++interruprcnt=4000)
{second++;
interruptcnt=0;
{
定义中断函数要注意:
1interrupt和using不能用于外部中断;
2使用using定义寄存器组时,要保证寄存器组切换在所控制的区域内,否则出错。
I/O函数
函数功能
_getkey从串行口读入一个字符
_getchar从串行口读入一个字符并输出该字符
gets从串行口读入一个字符串
ungetchar将读入的字符回送到输入缓冲区
putchar通过8051的串行口输出字符
printf按照一定的格式输出数据或字符串
sprintf按照一定的格式将数据或字符串输出到内存缓冲区
puts将字符串和换行符写入串行口
scanf将字符串和数据按照一定的格式从串行口读入
sscanf将格式化的字符串和数据送入数据缓冲区
vprintf将格式化字符串输出到内存数据缓冲区
vsprintf将格式化字符串和数字输出到由指针所指向的内存数据缓冲区
内部函数库
_crol_将char型变量循环向左移动指定位数后返回
_irol_将int型变量型循环向左移动指定位数后返回
_lrol_将long型变量循环向左移动指定位数后返回
_cror_将char型变量循环向右移动指定位数后返回
_iror_将int型变量循环向右移动指定位数后返回
_lror_将long型变量循环向右移动指定位数后返回
_nop_使单片机产生延时(相当于插入汇编指令NOP)
_testbit_对字节中的一位进行测试(相当于JBCbit)指令
绝对地址访问函数
CBYTE对8051单片机的存储空间进行字节寻址CODE区
DBYTE对8051单片机的存储空间进行字节寻址DATA区
PBYTE对8051单片机的存储空间进行字节寻址PDATA区
XBYTE对8051单片机的存储空间进行字节寻址XDATA区
CWORD对8051单片机的存储空间进行字寻址CODE区
DWORD对8051单片机的存储空间进行字寻址DATA区
PWORD对8051单片机的存储空间进行字寻址PDATA区
XWORD对8051单片机的存储空间进行字寻址XDATA区
3-29字节型空间访问示例
//头文件
{charch;
DBYTE[0x0040]=0x41;
//赋值
PBYTE[0x0002]=0x42;
XBYTE[0x0003]=0x43;
ch=CBYTE[0x0002];
//读取并输出
ch=%bx\n"
ch);
ch=DBYTE[0x0040];
ch=PBYTE[0x0002];
ch=XBYTE[0x0002];
}运行结果如下ch=6ach=41ch=42ch=43
3-30字型空间访问示例
{intch1;
DWORD[0x0040]=0x41;
PWORD[0x0002]=0x42;
XWORD[0X0002]=0X43;
ch1=CWORD[0x0002];
/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 语言程序设计 应用 基于 Proteus 仿真