单片机课后习题 - 图文

更新时间:2023-03-15 13:41:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

P148作业

5-5请分别定义下列变量:

(1) 片内RAM中无符号字符型变量x;

unsigned char data x;

(2) 片内RAM中位寻址区无符号字符型变量y,将y.0-y.2再分别定义为位变量

key_in、key_up、key_down; unsigned char bdata y; sbit key_in=y^0; sbit key_up=y^1; sbit key_down=y^2;

(3) 片外RAM中整型变量x,并指定变量x的绝对地址为4000H;

xdata int x _at_ 0x4000; 或 #define x XWORD[[0x2000]

(4)特殊功能寄存器变量PCON;

sfr PCON=0x87;

5-7用C51语言编程实现,片内扩展RAM的000EH单元和000FH单元的内容交换。 #include void main() {

unsigned char *pp1,*pp2,temp; }

5-9 试用C51语言编写程序实现将片内RAM 21H单元存放的两位BCD码数转换为十六进制数存入30H单元。 data unsigned char y1 _at_ 0x21;

AUXR&=0xfd; pp1=0x000e; pp2=0x000f; temp=*pp1; *pp1=*pp2; *pp2=temp;

data unsigned char y2 _at_ 0x30; void main() {

unsigned char temp; temp=y1; y1=(y1&0xf0)>>4; }

P208作业

7-7在STC12C5A60S2单片机中,假设系统的时钟频率为12MHz,利用定时/计数器T0,分别用汇编语言和C51编程实现在P1.0引脚输出周期为2s的方波。

分析:仿例题7-3,要产生周期2s的方波,需定时1s,一个定时器完成不了,可定时50ms,T0工作在方式1,然后利用R7对50ms定时中断计数20次来实现。选择12T模式,T0x12=0,f=12MHz,则需计数50000,初值为65536-50000=15536=3CB0H (1)汇编程序:

ORG 0000H

LJMP MAIN

ORG 000BH ;T0的中断向量入口地址

LJMP T0_INT ORG 0100H

MAIN:MOV SP,#0BFH ;初始化堆栈指针 MOV TMOD,# 01H ;T0工作在方式1 MOV TL0,#0B0H ;给T0写入初值 MOV TH0,#03CH

MOV R7,#20 ;利用寄存器R7计数20次

SETB EA ;开放总中断 SETB ET0 ;T1溢出中断允许 SETB TR0 ;启动T1开始工作 SJMP $

T0_INT:MOV TL0,#0B0H ;重新赋初值

MOV TH0,#03CH

y2=y1*10+(temp&0x0f);

DJNZ R7,NEXT

CPL P1.0

MOV R7,#20 ;重新赋给R7值50 NEXT:RETI

END

(1) C51程序:

#include/

sbit P1_0=P1^0; unsigned char i=0; void main( ) {

TMOD=0x01;//T0工作在方式1 TL0=0xB0;//给T0装入初值 TH0=0x3C; EA=1;//开放总中断 ET0=1;//T0溢出中断允许 TR0=1;//启动T0开始工作 while(1); }

void T0_INT( ) interrupt 1//T0中断服务程序 {

TH0=0x3C;

i++; if(i= =20) {

P1_0=!P1_0;

TL0=0xB0;//重新置入初值

i=0;

} }

7-8由P1口驱动8个指示灯,利用定时/计数器T1的定时功能分别用汇编语言和C51编程实现8个指示灯依次循环点亮(输出高电平),点亮间隔为1s,反复循环。

分析:仿照上题,T1需定时50ms,R7计数20次,达到定时1s的目的,每隔1s,循环一次,实现轮流点亮。 (1)汇编程序

ORG 0000H

LJMP MAIN

ORG 001BH ;T1的中断向量入口地址

LJMP T1_INT ORG 0100H

MAIN:MOV SP,#0BFH ;初始化堆栈指针 MOV TMOD,# 10H ;T1工作在方式1 MOV TL1,#0B0H ;给T1写入初值 MOV TH1,#03CH

MOV R7,#20 ;利用寄存器R7计数20次 MOV A,#01H

SETB EA ;开放总中断 SETB ET1 ;T1溢出中断允许 SETB TR1 ;启动T1开始工作 SJMP $

T1_INT:MOV TL1,#0B0H ;重新赋初值

MOV TH1,#03CH

DJNZ R7,NEXT ; R7减1不为0,说明中断次数未

;到20次,跳转到NEXT处返回

MOV P1,A; RL A ;为下一次做准备

MOV R7,#20 ;重新赋给R7值50 NEXT:RETI END

(2) C51程序:

#include

unsigned char i=0; unsigned char j; void main( ) {

TMOD=0x10;//T1工作在方式1 TL1=0xB0;//给T1装入初值 TH1=0x3C;

j=0x01;

EA=1;//开放总中断 ET1=1;//T1溢出中断允许 TR1=1;//启动T1开始工作 while(1); }

void T1_INT( ) interrupt 3//T1中断服务程序 {

TH1=0x3C;

TL1=0xB0;//重新置入初值 i++; if(i= =20) {

P1=j;//已定时中断20次 i=0;

j=_crol_(j,1);

} }

7-12 假设系统时钟频率为12MHz,利用PCA模块的功能,分别用汇编语言和C51编程实现在P1.3引脚上间断重复输出频率为450Hz的方波,持续和停止时间均为4s。

分析:将PCA模块的工作方式寄存器CCAPM0寄存器写为4DH,即PCA0设为时钟输出方式,从而可以在P1.3引脚自动翻转,输出方波,并允许PCA中断。要求方波频率为450hz,即周期为1/450,定时时间应设定为1/900s,选择计数器时钟来源为系统时钟频率的12分频,即工作方式寄存器CMOD设为00H,需要计数(1/900)(/12/12000000)=10000/9≈1111=0457H

个时钟脉冲,可将CL、CH初始值设为零,CCAP0H设为04H,CCAP0L设为57H,在每次PCA中断里:将计数值加到比较匹配寄存器里CCAP0H+=4,CCAP0L+=57H

4秒启动一次PCA计数(CR=1),4秒停止(CR=0);

4秒定时器由T1产生,工作在方式1定时50毫秒,计数时钟fosc/12 初值N,则(65536-N)*1=50000?N=15536=3cb0H (1)

汇编程序:

CCON EQU 0D8H;PCA控制寄存器 CMOD EQU 0D9H;PCA模式寄存器 CL EQU 0E9H;PCA定时器的低8位 CH EQU 0F9H;PCA定时器的高8位

CCAPM0 EQU 0DAH; PCA模块0的模式寄存器

CCAP0L EQU 0EAH;PCA模块0的捕获寄存器的低8位 CCAP0H EQU 0FAH;PCA模块0的捕获寄存器的高8位 AUXR EQU 8EH

CR BIT CCON.6;PCA定时控制位 CF BIT CCON.7;PCA溢出标志位 ORG 0000H LJMP MAIN ORG 001BH LJMP T1_INT ORG 003BH LJMP PCA_INT ORG 0100H MAIN:

CLR A

MOV CCON,A;//(P197) MOV CL,A; MOV CH,A;

MOV SP,#0BFH;初始化堆栈指针 MOV TMOD,#10H;T1工作在方式1

MOV TL1,#B0H;给T1写入初值 MOV TH1,#3CH;

ANL AUXR,#101111111H;//T1X12=0

MOV CCAPM0,#4DH;// 允许中断,输出方波

MOV CCAP0L,#57H; MOV CCAP0H,#04H;

MOV CMOD,#0H;//FOSC/12时钟计数 MOV R7,#80;利用寄存器R7计数80次 SETB EA; SETB ET1; SETB TR1; SETB CR SJMP $

T1_INT: MOV TL1,#B0H;给T1写入初值

MOV TH1,#3CH; DJNZ R7,NEXT; MOV C,CR CPL C MOV CR,C MOV R7,#80;

NEXT:RETI PCA_INT: PUSH PSW PUSH ACC CLR CCF0 MOV A,CCAP0L ADD A,#57H MOV CCAP0L,A MOV A,CCAP0H ADDC A,#04H

MOV CCAP0H,A POP ACC POP PSW RETI END C51程序:

#include unsigned char i=0; void main() {

TMOD=0x10; TL1=0xB0; TH1=0x3C; CMOD=0x00; AUXR&=0xBF; CCAPM0=0x4D; CCAP0L=0x57; CCAP0H=0x04; EA=1; ET1=1; TR1=1; CR=1; while(1); }

void T1_INT() interrupt 3 {

TH1=0xB0; TH1=0x3C; i++; if(i==80)

{ CR=!CR; i=0; } }

void pca_INT() interrupt 7 {

CCAP0L+=0x57; CCAP0H+=0x04; }

7-13假设系统的时钟频率为11.0592MHz,利用PCA模块的PWM功能分别用汇编语言和C51编程实现输出400Hz且占空比为60%的矩形波。

分析:仿照例题7-8,系统的时钟频率为11.0592MHz,根据公式PWM的频率

PCA的时钟源频率,计算出PCA的时钟源频率为102400Hz,用T0的溢出作为PCA

256时钟源,11059200?102400=108,即对系统时钟源fosc进行108级分频,设T0工作在1T模

256-CCAP0L式,T0的初值为256-108=148=80H,由占空比==0.6,可计算出

256=

CCAP0L=66H,CMOD寄存器应赋值为04H,CCAPM0寄存器初值为42H。

(1)汇编语言程序:

CCON EQU 0D8H;PCA控制寄存器 CMOD EQU 0D9H;PCA模式寄存器 CL EQU 0E9H;PCA定时器的低8位 CH EQU 0F9H;PCA定时器的高8位

CCAPM0 EQU 0DAH;PCA模块0的模式寄存器 CCAP0L EQU 0EAH;PCA模块0的捕获寄存器的低8位 CCAP0H EQU 0FAH;PCA模块0的捕获寄存器的高8位 AUXR EQU 8EH

CR BIT CCON.6;PCA定时控制位 CF BIT CCON.7;PCA 溢出标志位

ORG 0000H

CLR A MOV CCON,A

MOV CL,A;计数器初值复位 MOV CH,A

MOV TMOD ,#02H MOV TL0,#80H ;给T0赋初值 MOV TH0,#80H

MOV CMOD,#04H ;利用T0的溢出作PCA时钟源 MOV AUXR,#80H ;T0工作在1T模式

MOV CCAPM0,#42H ;允许P1.3引脚作脉宽调节输出 MOV CCAP0L,#66H ;用于输出占空比为60%的波形 MOV CCAP0H,#66H

SETB TR0 ;T0计数器启动工作 SETB CR ;PCA计数器启动工作 SJMP $ (2)C51程序:

#include //包含用于定义STC12C5Axx系列单片机片内资源的头文件 void main( ) {

CCON=0x00; //PCA控制寄存器清0 CL=0x00; //16位PCA计数器清0 CH=0x00;

TMOD=0x02;//T0工作在方式2 TL0=0x80;//给T0赋初值 TH0=0x80;

CMOD=0x04; // 利用T0的溢出作PCA时钟源

AUXR=0x80; // T0工作在1T模式

CCAPM0=0x42;//允许比较且作为PWM脉宽调节输出

CCAP0L=0x66;//控制模块0的输出占空比为40% CCAP0H=0x66; TR0=1;//T0开始工作

CR=1;//16位计数器开始工作 while(1); }

8-9甲乙两机利用串行口1的方式1实现双机通信,甲机将片内RAM中30H-3FH单元的内容传送到乙机片内RAM的50H-5FH单元,假设甲乙两机的波特率为2400bps,系统的时钟频率为11.0592MHz,试画出双机通信的电路图,并用汇编语言和C51分别编写相应的程序实现上述任务。

分析:甲乙两机都选择串行口1工作在方式3,9位异步通信方式,TB8作为奇偶校验位,甲机控制字SCON=0C0H,乙机SCON=0D0H。利用定时器T1工作在12T模式,方式2作为串行口的波特率发生器,TMOD=20H,设SMOD=0,PCON=7FH,波特率为2400bps,系统的时钟频率为11.0592MHz,可知T1的重装初值为F4H,

汇编子程序:

TRA_UART:MOV TMOD,#20H ANL AUXR,#0BFH MOV TL1,#0F4H MOV TH1,#0F4H ANL PCON,#7FH MOV SCON,#0C0H MOV R0,#30H

MOV R7,#10H SETB TR1 LOOP: MOV A,@R0 MOV C,P MOV TB8,C MOV SBUF,A WAIT: JNB TI,WAIT CLR TI INC R0

DJNZ R7,LOOP RET 已机接收子程序:

RES_UART: MOV TMOD,#20H MOV TL1,#0F4H MOV TH1,#0F4H ANL AUXR,#0BFH ANL PCON,#7FH MOV SCON,#0D0H MOV R0,#50H MOV R7,#10H SETB TR1 LOOP: NOP

WAIT: JNB RI,WAIT CLR RI MOV A,SBUF MOV C,P ANL C,/RB8 MOV F0,C MOV C,RB8

ANL C,/P ORL C,F0

JC ERROR MOV @R0,A INC R0

DJNZ R7,LOOP RET ERROR: … … RET

C语言程序:甲乙两机都选择方式1,8位异步通信方式,甲机的控制字SCON=40H,乙机的控制字SCON=50H,选择校验方式为和校验,其他不变 甲机的发送程序: #include unsigned char idata buf[16]; unsigned char pf; void main() {

unsigned char i,j; SCON=0x40; TMOD=0x20; PCON=PCON&0x7F; AUXR=AUXR&0xBF; TL1=0xF4; TH1=0xF4; TR1=1; pf=0;

for(i=0;i<16;i++) {

SBUF=buf[i]; pf+=buf[i];

while (TI==0); TI=0;

} SBUF=pf; while (TI==0); TI=0; } while(1); }

已机接收程序: #include unsigned char idata buf[16]; unsigned char pf; void error(); void main() {

unsigned char i,j; SCON=0x50; TMOD=0x20; PCON=PCON&0x7F; AUXR=AUXR&0xBF; TL1=0xF4; TH1=0xF4; TR1=1; pf=0;

for(i=0;i<16;i++) { while(RI==0) ;

RI=0;

buf[i] =SBUF; pf+=buf[i]; }

while (RI==0); RI=0;

if(SBUF^pf) error(); while(1); }

void error() {………..}

11-4 设计电路并编写程序:使用8255A驱动2个共阳极数码管,从0开始显示,每隔1秒钟加1,直到99,反复循环。

设计电路如图习题11—4。(此处74HC373作驱动之用,不是锁存)

汇编语言程序段:

APORT EQU 0F8FFH ;A口 BPORT EQU 0F9FFH ;B口 CONPORT EQU 0FBFFH ;控制字端口 AUXR EQU 8EH ORG 0H LJMP MAIN MAIN: MOV SP,#0AFH

ORL AUXR,#00000010B MOV A,#80H

MOV DPTR,#CONPORT MOVX @DPTR,A NOP

NOP

NOP NOP NOP

BEGIN:MOV R0,#00H LOOP:MOV B,#10 MOV A,R0 DIV AB

MOV DPTR,#TAB

MOVC A,@A+DPTR

XCH A,B

MOVC A,@A+DPTR MOV DPTR,#APORT

MOVX @DPTR,A MOV A,B

MOV DPTR,#BPORT MOVX @DPTR,A

INC R0

LCALL DELAY_1S CJNE R0,#100,LOOP LJMP BEGIN

DELAY_1S:MOV R7,#42H DL1: MOV R6,#0DAH DL0: MOV R5,#0CFH

DJNZ R5,$ DJNZ R6,DL0

DJNZ R7,DL1 RET

TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,092H,082H,0F8H,080H,090H ;TAB是0-9对应的段码值表 END C51程序:

#include #include #include

#define APORT XBYTE[0XF8FF] #define BPORT XBYTE[0XF9FF] #define CONPORT XBYTE[0xFBFF]

unsingned char code seg[10]={0xC0,0xF9,0xA4, 0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; void delay_1s(); void main() {

unsinged char i; CONPORT=0x80; while(1) {

for(i=0;i<100;i++) {

APORT=seg[i/10]; BPORT=seg[i]; delay_1s(); } } }

void delay_1s() {

unsinged char a,b,c; for(c=142;c>0;c--)

} 11-8

for(b=168;b>0;b--)

for(a=250;a>0;a--);

如图11-46所示,在P1.0-P1.7引脚连接8个按键,分别定义为1号、2号….8

号,在P3口连接一个共阳极数码管,编写程序,使8个按键中任意一个按下时,数码管上显示对应的键序号。

图11-46 习题11-8题的电路

汇编语言程序:

ORG 0000H LJMP MAIN ORG 0100H

MAIN: MOV SP,#0AFH

MOV P1,#0FFH

NOP NOP NOP

LOOP:MOV A,P1

CJNE A,#0FFH,LOOP1 SJMP LOOP

LOOP1:LCALL DELAY_15ms

MOV A,P1

CJNE A,#0FFH,LOOP2 SJMP LOOP

LOOP2:

JNB ACC.0,KEY1 JNB ACC.1,KEY2 JNB ACC.2,KEY3

JNB ACC.3,KEY4 JNB ACC.4,KEY5

JNB ACC.5,KEY6 JNB ACC.6,KEY7 JNB ACC.7,KEY8 LJMP LOOP

KEY1: MOV P3,#0F9H

AJMP LOOP

KEY2: MOV P3,#0A4H

AJMP LOOP

KEY3: MOV P3,#0B0H

AJMP LOOP

KEY4: MOV P3,#99H

AJMP LOOP

KEY5: MOV P3,#92H

AJMP LOOP

KEY6: MOV P3,#82H

AJMP LOOP

KEY7: MOV P3,#0F8H

AJMP LOOP

KEY8: MOV P3,#80H

AJMP LOOP

DELAY_15ms:MOV R6,#177 DL0:

C51程序:

#include unsigned char temp,temp1; void delay_15ms(); void KEY1(); ……

void KEY8(); void main() { P1=0xFF; while(1) {

temp=P1; if(temp!=0xFF) {

delay_15ms(); temp=P1; if(temp!=0xFF) {

switch(temp) {

case 0xFE:KEY1();break; case 0xFD:KEY2();break;

MOV R5,#0 DJNZ R5,$ DJNZ R6,DL0 RET END

图11-48 习题11-12题电路图

分析:P2.3驱动个位LED显示8,其段码为80H,P2.2驱动十位LED显示7,其段码为F8H,P2.1驱动百位LED显示6,其段码为82H,P2.0驱动千位LED显示5,其段码为92H,段码从P0口输出。P2.3、P2.2 、P2.1、P2.0作为输出位选端,加入小功率PNP型三极管9012增强驱动能力。限流电阻为330Ω,使两位LED动态显示时,每一段的电流大约为10mA。

取刷新频率为50Hz,刷新周期20ms,共4个数码管,所以每隔5ms就要交替刷新一个数码管的显示状态。选择延时5ms或更短时间即可 (1) 汇编语言程序:

ORG 00H

LJMP START ORG 80H START: MOV SP,#50H LLOOP: MOV 30H,#5 MOV R0,#30H MOV R1,#0FEH

MOV R7,#4 LOOP:

MOV DPTR,#TABLE MOV A,@R0 MOVC A,@A+DPTR MOV P0,A INC @R0 MOV A,R1 MOV P2,A RL A ;左移 MOV R1,A ACALL DELAY DJNZ R7,LOOP SJMP LLOOP DELAY:

;延时5ms程序

MOV R3,#60 DELAY1: MOV R2,#250 DELAY3:

DJNZ R2,DELAY3 DJNZ R3,DELAY1 RET

TABLE: ;共阳极八段码键值表

DB C0H,F9H,A4H,B0H,99H,92H DB 82H,F8H,80H,90H,88H,83H DB C6H,A1H,86H,8EH END (2)C51程序: #include unsigned char var1,var2;

unsigned char code seg[ ]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x 82,0xF8,0x80,0x90,0x88,0x83,0x C6,0xA1,0x86,0x8E}

unsigned char code xianshi[]={5,6,7,8} void main( ) {

unsigned char i,j,weixuan; {

while(1)

weixuan=0xfe; for(i=0;i<4;i++)

{

var1=xianshi[i];;//取待显示的数字

} } }

void delay( ) {

unsigned char a,b; for(a=142;a>0;a--)

var2=seg[var1]; //取该数字对应的字段码 P0=var2; P2=weixuan; delay();

weixuan=_crol_(weixuan,1);

for(b=250;b>0;b--);

}

或用定时器做定时 ORG 0000H LJMP MAIN ORG 001BH LJMP T1_INT ORG 0100H

MAIN: MOV SP,#0BFH SETB P2.0 SETB P2.1 SETB P2.2 SETB P2.3 MOV TMOD,#10H MOV TL1,#78H MOV TH1,#0ECH MOV R7,#4 SETB EA SETB ET1 SETB TR1 SJMP $

T1_INT: MOV TL1,#78H MOV TH1,#ECH CJNE R7,#4,NEXT1 SETB P2.3 CLR P2.0 MOV P0,#092H DEC R7 RETI

NEXT1: CJNZ R7,#3,NEXT2 SETB P2.0 CLR P2.1 MOV P0,#082H DEC R7 RETI

NEXT2: CJNZ R7,#2,NEXT3 SETB P2.1 CLR P2.2 MOV P0,#0F8H DEC R7 RETI

NEXT3: CJNZ R7,#1,EXIT SETB P2.2 CLR P2.3 MOV P0,#080H EXIT: MOV R7,#4 RETI END

C51程序:

#include #define uchar unsigned char #define uint unsigned int sbit P2_0=P2^0; sbit P2_1=P2^1; sbit P2_2=P2^2; sbit P2_3=P2^3; uchar i=0; void main() {

P2_0=1 P2_1=1 P2_2=1 P2_3=1 TMOD=0x10; TL1=0x78; TH1=0xEC; EA=1; ET1=1; TR1=1; while(1); }

void T1_INT() interrupt 3 {

TL1=0x78; TH1=0xEC; i++; switch(i) {

case 1: P2_3=1;P2_0=0;P0=0x92;break; case 2:P2_0=1;P2_1=0;P0=0x82;break; case 3:P2_1=1;P2_2=0;P0=0xF8;break; case 4:P2_2=1;P2_3=0;P0=0x80;i=0;break; default: i=0; } }

本文来源:https://www.bwwdw.com/article/lg7v.html

Top