单片微型计算机原理
学 院
班 级
学 号
姓 名
指导教师
成 绩
20##年6月
l 硬件实验:
实验一:定时器中断实验
实验内容:fosc=11.0592MHz,T0方式2产生定时中断实现秒表功能:数码管后两
位显示10ms;前两位显示秒数;K1/K2/K3键分别启动/停止/清零,按键操作不
分先后
实验程序流程图:
主程序流程图: 中断程序流程图:
实验程序:
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP INTT0
ORG 0100H
MAIN: MOV SP,#70H
CALL INI_ALL
LOOP: CALL DISPLAY
MOV DPTR,#8000H
MOVX A,@DPTR
JB ACC.7,NEXT
SETB TR0
NEXT: JB ACC.6,NEXT1
CLR TR0
NEXT1: JB ACC.5,LOOP
MOV R7,#0H
MOV R6,#0H
MOV R5,#0H
LJMP LOOP
/*INTT0*/
INTT0: PUSH PSW
PUSH ACC
INC R5
CJNE R5,#40,CMP1
CMP1: JC GOON
MOV R5,#0H
INC R6
CJNE R6,#100,CMP2
CMP2: JC GOON
MOV R6,#0H
INC R7
CJNE R7,#100,CMP3
CMP3: JC GOON
MOV R7,#0H
GOON: POP ACC
POP PSW
RETI
/*INIALL*/
INI_ALL:MOV R7,#0H
MOV R6,#0H
MOV R5,#0H
MOV IE,#82H
MOV TMOD,#02H
MOV TH0,#25
MOV TL0,#25
RET
/*DISPLAY*/
DISPLAY:MOV DPTR,#TABLE
MOV A,R7
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV 33H,A
MOV A,B
MOVC A,@A+DPTR
MOV 32H,A
/**/
MOV A,R6
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV 31H,A
MOV A,B
MOVC A,@A+DPTR
MOV 30H,A
/**/
MOV DPTR,#8000H
MOV A,33H
MOVX @DPTR,A
MOV DPTR,#8100H
MOV A,32H
MOVX @DPTR,A
MOV DPTR,#8200H
MOV A,31H
MOVX @DPTR,A
MOV DPTR,#8300H
MOV A,30H
MOVX @DPTR,A
RET
TABLE: DB 88H,0AFH,0C4H,86H,0A3H,92H,90H,8FH,80H,82H
END
实验结果:数码管后两位显示ms计数,前两位显示s计数,按K1键启动计数,K2键停止计数,K3键清零。可实现秒表功能。
实验二:驱动蜂鸣器实验
实验内容:使P3.5端口输出周期为1S的方波信号。并通过三极管驱动一个直流小喇叭,使其发出断续的鸣响。
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV SP,#70H
START: CPL P3.5
LCALL DELAY
LJMP START
DELAY: MOV R7,#200
Y: MOV R6,#100
X: NOP
DJNZ R6,X
DJNZ R7,Y
RET
END
实验结果:蜂鸣器发出声响。
实验三:显示管增一显示
实验内容:编写程序,使数码管从0000自增一加至9999,然后再自动清零循环。
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV 30H,#0H
MOV 31H,#0H
MOV 32H,#0H
MOV 33H,#0H
MOV R0,#1
START: LCALL DELAY
LCALL CONVERT
LCALL DISPLAY
INC R0
CJNE R0,#255,XX
LJMP START
XX: JC START
JNC MAIN
CONVERT:MOV A,R0
MOV B,#10
DIV AB
MOV 30H,B
MOV B,#10
DIV AB
MOV 31H,B
MOV 32H,A
RET
DISPLAY:MOV A,30H
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#8300H
MOVX @DPTR,A
MOV A,31H
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#8200H
MOVX @DPTR,A
MOV A,32H
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#8100H
MOVX @DPTR,A
MOV A,33H
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV DPTR,#8000H
MOVX @DPTR,A
RET
DELAY: MOV R7,#100
Y: MOV R6,#50
X: NOP
DJNZ R6,X
DJNZ R7,Y
RET
TABLE: DB 88H,0AFH,0C4H,86H,0A3H,92H,90H,8FH,80H,82H
END
实验结果:八段数码显示管如题目要求所示自增一显示。
l 软件实验
实验一:数据传送实验
实验内容:编写程序,将内部RAM中的30H-5FH中的数据设置为55H;
(1)将其中内容传送到90H开始的内部RAM中去。
(2)将其中内容传送到200H开始的外部RAM中去。
实验程序流程图:
实验程序:ORG 0000H
LJMP MAIN
ORG 0100H
MAIN: MOV SP,#70H
MOV R0,#30H
MOV R7,#30H
MOV A,#55H
LOOP1: MOV @R0,A
INC R0
DJNZ R7,LOOP1
MOV R0,#30H
MOV R7,#30H
MOV R1,#90H
LOOP2: MOV A,@R0
MOV @R1,A
INC R0
INC R1
DJNZ R7,LOOP2
WAIT: SJMP WAIT /*SJMP $*/
END
实验结果:
内部RAM,30H-5FH单元内都为55H。
内部RAM,90H开始的单元内都为55H。
外部RAM,200H开始的单元内都为55H
实验二:数据分类与校验实验
实验内容:编写程序,将内部RAM中30H-5FH中的数据设置为1-48;并将其中奇数传送到90H开始的内部RAM中;将30H-5FH中的数据设置按照奇校验设置最高位。
实验程序流程图:
实验程序:
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN: MOV SP,#70H
MOV R0,#30H
MOV R7,#30H
MOV A,#1
LOOP1: MOV @R0,A
INC R0
INC A
DJNZ R7,LOOP1
MOV R0,#30H
MOV R7,#30H
MOV R1,#90H
LOOP2: MOV A,@R0
INC R0
JB 0E0H,TRANS
JMP NTRANS
TRANS: MOV @R1,A
INC R1
NTRANS:DJNZ R7,LOOP2
END
实验结果:
内部RAM中30H-5FH中的数据为1-48;其中奇数传送到90H单元。
30H-5FH中的数据设置按照奇校验设置最高位送到90H单元内。
程序段如下:
//奇校验设置最高位
MOV R0,#30H
MOV R7,#30H
MOV R1,#90H
LOOP3: MOV A,@R0
INC R0
JNB P,TRANS2
JMP NTRANS2
TRANS2:SETB 0E7H
MOV @R1,A
INC R1
NTRANS2:DJNZ R7,LOOP3
实验三:简单算术运算
实验内容:编写程序,计算1-100的累加和。结果存放于内部RAM的30H、31H中,低字节在前。
实验程序流程图:
实验程序:
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN: MOV SP,#70H
MOV R0,#30H
MOV R1,#31H
MOV @R0,#0
MOV @R1,#0
MOV B,#1
MOV R7,#100
L1: MOV A,@R1
ADD A,B
MOV @R1,A
MOV A,@R0
ADDC A,#0
MOV @R0,A
INC B
DJNZ R7,L1
END
实验结果:
(30H)=13H,(31H)=0BAH,即结果为13BAH=5050D。
实验四:定点数算术运算实验
实验内容:编写2字节乘2字节子程序。乘数位于R2R3,被乘数位于R4R5。结果存放于R4R5R6R7内。
实验说明:
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV R2,#04H
MOV R3,#03H
MOV R4,#02H
MOV R5,#01H
MOV R6,#0H
MOV R7,#0H
MOV R0,#16D/*JISHU*/
CLR C
LOOP: MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV 26H,R6
MOV 27H,R7
MOV A,R2
CJNE A,26H,NEXT1
NEXT1: JNC NEXT2
MOV A,R3
CJNE A,27H,NEXT3
NEXT3: JNC NEXT2
CLR C
MOV A,R7
SUBB A,R3
MOV R7,A
MOV A,R6
SUBB A,R2
MOV R2,A
SETB C
NEXT2: DJNZ R0,LOOP
WAIT: SJMP WAIT
END
实验结果:当(R4R5)=21H,(R2R3)=43H时,运算结果为(R4R5R6R7)=08A3H。
实验五:数制转换实验一
实验内容:编写程序,将内部RAM中30H中的二进制数据转换为十进制数据并存放在31H、32H、33H中。
实验程序流程图:
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV 30H,#0ABH
MOV A,30H
MOV B,#100D
DIV AB
MOV 31H,A
MOV A,B
MOV B,#10D
DIV AB
MOV 32H,A
MOV 33H,B
WAIT: SJMP WAIT
END
实验结果:假设(30H)=0ABH,则(31H、32H、33H)=(01、07、01)。
实验六:数制转换实验二
实验内容:编写程序,将内部RAM中30H-3FH中的16进制数据(0-F)转换为ASCII码并存放在40H-4FH中。
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV R0,#30H
MOV A,#0H
MOV R2,#16D
LOOP1: MOV @R0,A
INC A
INC R0
DJNZ R2,LOOP1
MOV R0,#30H
MOV R1,#40H
MOV R2,#16D
LOOP: MOV A,@R0
INC R0
CLR C
SUBB A,#10D
JC SMALL
ADD A,#7
SMALL: ADD A,#3AH
MOV @R1,A
INC R1
DJNZ R2,LOOP
WAIT: SJMP WAIT
END
实验结果:
实验七:数据统计实验一
实验内容:编写程序,首先将内部RAM中30H-7FH中的数据设置为50H-9FH。然后编写程序统计该区域内大于80H的个数,结果存放在寄存器B内。
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV R0,#30H
MOV A,#50H
MOV R2,#80D
LOOP1: MOV @R0,A
INC A
INC R0
DJNZ R2,LOOP1
MOV R0,#30H
MOV R1,#0H
MOV R2,#80D
LOOP: CJNE @R0,#81H,NEXT
NEXT: JC NEXT1
INC R1
NEXT1: INC R0
DJNZ R2,LOOP
MOV B,R1
WAIT: SJMP WAIT
END
实验结果:首先将30H-7FH中的数据设置为50H-9FH
统计该区域内大于80H的个数,结果存放在寄存器B内,(B)=20H。
实验八:数据统计实验二
实验内容:编写程序,首先将内部RAM中30H-7FH中的数据设置为50H-9FH;然后统计该区域内的奇数个数,存放在R6中,正数个数放在R7。
实验程序:
ORG 0H
LJMP MAIN
ORG 0100H
MAIN: MOV R0,#30H
MOV A,#50H
MOV R2,#80D
LOOP1: MOV @R0,A
INC A
INC R0
DJNZ R2,LOOP1
MOV R0,#30H
MOV R6,#0H/*JI*/
MOV R7,#0H/*ZHENG*/
MOV R2,#80D
LOOP: MOV A,@R0
JNB ACC.0,NEXT1
INC R6
NEXT1: JB ACC.7,NEXT2
INC R7
NEXT2: INC R0
DJNZ R2,LOOP
WAIT: SJMP WAIT
END
实验结果:
首先将30H-7FH中的数据设置为50H-9FH
统计的奇数个数存放在R6中,(R6)=28H
摘要
本次实验是软硬件相结合的实验,通过传感器得到的阻值与其它电阻,可以搭建一个电桥,将水温转化为电压,然后通过放大器将电压放大到所需要的值,将所得的电压送入单片机的AD转换电路,将模拟信号转换成数字信号,从而在单片机的液晶屏上显示当前的温度。此烧水壶是可控制的,即设定温度,使水加热到设定温度且保温,此控制算法采用PID控制算法来控制继电器的通断,来保证水温恒定在设定温度处。
1.传感器:Pt100铂热电阻
2.测量放大器:自己设计与搭建
3.被控对象:400W电热杯,约0.5公斤自来水
4.执行机构:12V驱动,5A负载能力的继电器
5.控制系统:51单片机
6.控制算法:PID
7.温度范围:环境温度~100度
8.测量误差1度,控制误差2度
热电阻传感器是利用导体或半导体的电阻值随温度变化而变化的原进行测温的。
热电阻的工作原理:温度升高,金属内部原子晶格的振动加剧,从而使金属内部的自由电子通过金属导体时的阻碍增大,宏观上表现出电阻率变大,电阻值增加,我们称其为正温度系数,即电阻值与温度的变化趋势相同。
说明:电位器R10用来调节偏置电压,而电位器R7则用来调节增益。实验时,用R10来调节零点,用R7来调节满度。该电路将0℃-100℃转换为0-5V电压。
上述电路图采用仪表放大器,将铂热电阻两端的电压U2与电位器R10两端的电压U1差放大,放大器输出电压U0与电压差的关系为:
由铂热电阻阻值与水温的关系可知,铂热电阻的范围是。则整理得:
而仪表放大器的输出电压为0~5V,所以放大倍数大约为:5/0.04=125。
当假设R8/R4=2时,R2/R7=30
由此,我们可以选择R8=20K,R4=10K,R2=10K,R7=2K的电位器,为了使放大器的性能更好,我们可以把R10选为200欧姆的电位器。调节R,可以调节电平,调节R7是调节放大倍数。
调节测量放大电路的电位器R2和R7,使差分放大器输出0-5V电压,送入单片机。单片机的A/D转换电路将0-5V电压划分为1024个量化台阶,即0-5V对应0-1023。用10位二进制数表示。采样读出DIO口的连续10个电平值,当量化台阶为1000时,刚好1000对应的是100摄氏度,所以只需把采样读出的电平值左移一位,即可换算出对应的温度值。
主要思想:首先AD转换器TLC1549是10位的,故转换最大值为1023,为显示及计算方便,只取到1000,对应输入电压值4.88V,对应显示温度值100摄氏度.由于温度传感器基本是线性的,故0摄氏度对应电压值0V,取放大器放大倍数约100倍,将输入的微小电流放大.程序中计时器定时为50ms,每50 次也就是2.5 秒进行一次AD 转换,显示及PID计算,也就是2.5 秒的加热周期,故占空比的比例为五十分之几,这个几是PID 计算出来的u 换算出来的.u的取值有负有正,且大小范围非常大,不好确定,故对u经行比例压缩,u越大加热的占空比就越高,u为0对应不加热,这样就将u转换为占空比.虽然可能精度不够,但基本实现了温度的控制.关于PID三个系数的确定问题,比例项应大,使温度反应快一点.积分微分项系数也稍微取大一点,使震荡次数下降,稳定值波动较小.系统也许需要比较长的时间才能准确的跟踪设定值.
TMOD设置
1.采用T1定时/计数器,工作在方式1下,见下表:
所以 TMOD=10H
2.开中断:EA=1;
定时器T1开:ET1=1
3.TH1、TL1设置
定时时间设为50ms,所以
50×10-3=(216-初始值)×(12/11.0592)×10-6
解得: 初始值=19456=01001100 00000000B
因此:TH1=01001100B=4CH TL1=00000000B=00H
程序中需用到的系统地址
A1A0组合分别是00:写指令;01:写数据;10:读指令;11:读数据
系统地址:0A000H 0A001H 0A002H 0A003H
源程序附在附录里面。
在电热水杯加热的初始阶段,继电器始终保持接通状态,电热水杯全速加热。当水温到达50℃以上,继电器在PID算法的控制下开始通断交替,且随着水温的升高,继电器接通的时间逐渐减少,断开的频率逐渐增大。当水温到达设定温度左右(±2℃)时,继电器通断时间比例不再变化,电热水杯处在保温状态,水温恒定在设定温度上下。经过调试和温度的校后显示的温度值是比较准确的,误差大约在零点几摄氏度内.在做温度控制的时候,由于我显示出了占空比值和时间t,故调整系数很方便和直观.控制误差大约一摄氏度左右,也是符合要求的,但系统的超调量还是比较大的,故做了适当软件上的调整,如温度超过设定值时直接将继电器断开,而不是等待PID 做出反应,毕竟温度控制是一个大滞后性和大惯性的系统.
3年大学时光中,觉得最有用的课程就是这些实验了,它让我们学有所用,而不仅仅是各种理论,而是通过实践来巩固深入理解理论。这门实验课让我们不仅在软件上花了大量的功夫,代码力求精益求精;而且.在实际的调试中,还是发现软件只是一方面的内容,外硬件的优劣也是影响系统性能和精度的致命因素.尤其是做控制的时候和调整温度的时候,一个可靠的硬件可以省下不少功夫.温度控制系统的设计让我们学会的不仅仅是对单片机的内部结构的进一步理解与运用,还在上一次实验的基础上进一步提高运放集成电路设计与运用的能力。
附:源程序
#include <REG52.H>
#include <absacc.h>
#include <intrins.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
#define KP 0.55 //比例系数
#define KI 0.02 //积分系数
#define KD 0.1 //微分系数
sbit pout=P1^7;
sbit SCLK=P1^2;
sbit DIO=P1^3;
sbit AD_CS=P1^4;
uchar num1[13]={0x53,0x45,0x54,0x54,0x3A,0,0,0,0x2E,0,0xDF,0x43};
uchar num2[13]={0x4E,0x4F,0x57,0x54,0x3A,0,0,0,0x2E,0,0xDF,0x43};
unsigned int settemp=500,nowtemp;
unsigned char timecount=0;
bit adflag,showflag; //ad标志位
unsigned char duty=0,duty_tem=0; //输出控制量
float el,en=0,es=0;
float p_out,i_out,d_out;
void write();
void BUSY();
void LCD_inti();
void delay(uchar n)
{
int ii,jj;
for(ii=0;ii<n;ii++)
for (jj=0;jj<120;jj++);
return;
}
void keyscan()
{ uchar key=0,tempKey=0;
XBYTE[0x8fff]=0x0f;
delay(100);
tempKey=XBYTE[0x8fff];//读取按键
tempKey&=0x0f;
delay(100);
key=XBYTE[0x8fff];//再次读取按键
key&=0x0f;
if(key==tempKey)
{
while(key==tempKey)//等待按键弹起
{
key=XBYTE[0x8fff];
key&=0x0f;
}
switch(tempKey)
{
case 1:if(settemp<=900)settemp+=100;break;
case 2:if(settemp>100)settemp-=100;break;
case 4:if(settemp<=990)settemp+=10; break;
case 8:if(settemp>10)settemp-=10; break;
default: break;
}
}
}
void writeData(uchar data1)
{
while(XBYTE[0xa001]&0x80);//等待可写
XBYTE[0xa002]=(data1);//向数据端口写入数据
}
void writeString(uchar data1[],int len)
{
int k=0;
for(k=0;k<len;k++)//写入字符串
writeData(data1[k]);
}
//LCD初始化
void LCD_inti()
{
BUSY();
XBYTE[0xa000]=0x01;
BUSY();
XBYTE[0xa000]=0x06;
BUSY();
XBYTE[0xa000]=0x1c;
BUSY();
XBYTE[0xa000]=0x38;
BUSY();
XBYTE[0xa000]=0x0c;
}
void BUSY()
{
uchar BUSYBF=0;
while(1)
{
BUSYBF=XBYTE[0xa001];
if(BUSYBF <0x80) break;
}
return;
}
//AD初始化
void AD_init()
{
AD_CS=1; //必须为高
SCLK=1; //上升沿有效
DIO=1; //置高
}
unsigned int AD() //本次AD读取上一次的值
{
uint temp=0;
uchar i;
AD_CS = 0;
SCLK = 0;
for(i=0;i<10;i++)
{
temp <<=1;
temp |= DIO;
SCLK = 1;
SCLK = 0;
}
AD_CS = 1;
delay(256); //延迟>17us
return temp;
}
//定时器初始化
void timer_init()
{
TMOD=0x10; //T1:计时器
EA=1; //全局中断允许
TH1=0x4C;
TL1=0x00; //初值19456
ET1=1; //允许定时器中断
timecount=0;
TR1=1; // 开始计时
}
void OnTimer1() interrupt 3
{
TR1=0; // 停止计时
EA=0;
TH1=0x4C;
TL1=0x00;// 初值19456
timecount++;
if (timecount>50) //2.5秒进行一次PID控制
{
timecount=1;
adflag=1;//ad采样 开始控制
}
/* if (timecount<=duty)
{
pout=1;
}
else
{
pout=0;
}*/
if (timecount%10==0)
{showflag=1; //0.5秒对屏幕进行一次刷新
//nowtemp+=1;
}
TR1=1; // 开始计时
EA=1;
}
//pid控制算法
pid()
{
el=en;
en=(signed)settemp-(signed)nowtemp;
es+=en;
p_out=KP*en; //比例项输出
i_out=KI*es; //积分项输出
d_out=KD*(en-el); //微分项输出
if(i_out>100) //积分分离
i_out=100;
if(i_out<-100)
i_out=-100;
duty_tem=p_out+i_out+d_out; //总输出量
if(duty_tem<0)
duty_tem=0;
if(duty_tem>=100)
duty_tem=100;
duty=floor(duty_tem)/2; //u最大值为50
if(duty_tem<0) pout=1;
else pout=0;
return (pout);
}
///////////////////////
main()
{
pout=1;
LCD_inti();
AD_init();
timer_init();
if (adflag)
{
nowtemp=AD();
nowtemp=AD();
adflag=0;
pid();
}
while (1)
{
keyscan();
if (showflag)
{
LCD_inti();
nowtemp=AD();
nowtemp=AD();
num1[5]=settemp/1000+48;
num1[6]=(settemp/100)%10+48;
num1[7]=(settemp/10)%10+48;
num1[9]=settemp%10+48;
XBYTE[0xa000]=0x80;
writeString(num1,13);
num2[5]=nowtemp/1000+48;
num2[6]=(nowtemp/100)%10+48;
num2[7]=(nowtemp/10)%10+48;
num2[9]=nowtemp%10+48;
XBYTE[0xa000]=0xc0;
writeString(num2,13);
showflag=0;
}
if (adflag)
{
nowtemp=AD();
nowtemp=AD();
pid();
adflag=0;
}
}
}
滨江学院微机原理与接口技术综合实验报告题目:简易电子琴设计学号:学生姓名:XXX院系:滨江学院专业:指导教师:二OXX年月日【摘要…
51单片机课程设计报告学院:专业班级:姓名:指导教师:设计时间:51单片机课程设计一、设计任务与要求1.任务:制作并调试51单片机…
08424020xx单片微型计算机原理学院班级学号姓名指导教师成绩120xx年6月08424020xx硬件实验实验一定时器中断实验…
08424020xx硬件实验实验一定时器中断实验实验内容fosc110592MHzT0方式2产生定时中断实现秒表功能数码管后两位显…
班级姓名学号单片机实验报告实验一CPU片内外清零1CPU片内RAM清零一实验目的掌握MCS51汇编语言的设计了解单片机的寻址方式以…
51单片机课程设计报告学院:专业班级:姓名:指导教师:设计时间:51单片机课程设计一、设计任务与要求1.任务:制作并调试51单片机…
绪论单片机应用简述电子时钟简介电子时钟的基本特点任务要求设计方案控制系统的硬件设计芯片的选择AT89S51的功能概述AT89S51…
51单片机精简开发板的组装及调试实训报告为期一周的单片机实习已经结束了通过此次实训让我们掌握了单片机基本原理的基础单片机的编程知识…
重庆科技学院学生实习实训总结报告学院电气与信息工程学院专业班级XXXXXX学生姓名XXX学号20xxXXXXXX实习实训地点逸夫科…
JINGCHUUNIVERSITYOFTECHNOLOGY单片机原理及应用课程设计报告题目电子时钟专业电气工程及其自动化班级20x…
时间过得真快,不经意间,一个学期就到了尾声,进入到如火如荼的期末考试阶段。在学习单片机这门课程之前,就早早的听各种任课老师和学长学…