实验报告待打印word.docx
《实验报告待打印word.docx》由会员分享,可在线阅读,更多相关《实验报告待打印word.docx(26页珍藏版)》请在冰豆网上搜索。
实验报告待打印word
微机控制实验报告
姓名:
学号:
班级:
目录
实验一代码转换1
一、实验目的1
二、实验任务1
三、程序代码与运行结果1
四、实验总结4
实验二液晶显示程序设计5
一、实验目的5
二、实验任务5
三、程序代码与运行结果5
四、实验总结9
实验三串行通讯程序设计10
一、实验目的10
二、实验任务10
三、程序代码与运行结果10
四、实验总结12
实验四A/D转换实验13
一、实验目的13
二、实验任务13
三、程序代码与运行结果13
四、实验总结17
实验五D/A转换实验18
一、实验目的18
二、实验任务18
三、程序代码与运行结果18
四、实验总结22
实验一代码转换
一、实验目的:
熟悉C8051单片机常用代码之间的转换方法。
二、实验任务:
1.设计并调试一个程序,将片内20H单元中8位无符号二进制数转化为BCD码,结果存入以30H开始的单元中。
2.设计并调试一个程序,将片内以20H开始的单元中的4字节无符号二进制数转化为BCD码,结果存入以30H开始的单元中,低位字节在低地址端。
3.设计并调试一个程序,将累加器A中的二进制数(0~F)转化为ASCⅡ码,结果仍放在A中。
三、实验代码及运行结果:
A.实验任务1对应的程序代码及结果:
1,程序代码
#include
main()
{
unsignedlongchar*p;
unsignedlongchar*q;
unsignedlongchartemp;//4个字节
p=0x20;//对应20H单元
q=0x30;//对应30H单元
*p=0x11;//对20H单元赋初值
temp=*p;//将20H单元内容放入temp中
*q=temp%10;//将20H中个位上的值赋给30H中
q++;//指针指向31H
*q=temp/10%10;//将20H中十位上的值赋给31H中
q++;//指针指向32H
*q=temp/100;//将20H中十位上的值赋给32H中
while
(1);//自跳转指令,系统处于等待中
}
2,程序运行结果
由于在此实验中利用仿真的方法没有实际连接单片机,所以我们可以从Keil-2自带的仿真模块看到运行的结果,即30H以后各个单元内容如下图1-1所示:
图1-1
B.实验任务2对应的程序代码及结果:
1,程序代码
#include
main()
{
unsignedlongint*p;
unsignedlongint*q;
unsignedlonginttemp;//4个字节
p=0x20;//对应20H单元
q=0x30;//对应30H单元
*p=0x11111111;//对20H-23H这几个单元赋初值
temp=*p;
while(temp!
=0)//判断是否结束
{
*q=temp%10;
q++;
temp=temp/10;//完成将各位依次赋给30H以后的单元
}
while
(1);//自跳转指令,系统处于等待中
}
2,程序运行结果
同任务1我们可以从Keil-2自带的仿真模块看到运行的结果,即30H以后各个单元内容如下图1-2所示:
图1-2
C.实验任务3应的程序代码及结果:
1,程序代码
#include
main()
{
unsignedchartemp;//定义中间变量
ACC=0x02;//给累加器赋初值(此处为2)
temp=ACC;//将累加器初值给中间变量
if(temp>=0&&temp<=9)//判断初值为多少
temp=temp+0x30;//如果是0–9那么ASCII码为值加0x30
else
temp=temp+65;//如果是A–F那么ASCII码为值加65
ACC=temp;//可以得到对应的ASCII码
while
(1);
}
2,程序运行结果
同任务1我们可以从Keil-2自带的仿真模块看到运行的结果如下图1-3所示,由于原值为2,则累加器中中结果为32H:
图1-3
四、实验总结:
这次实验是本学期的第一次实验,虽然本科学过C51的相关课程,但是以及有一年多的时间没有接触,感觉自己已经生疏了很多,所以尽管这次试验的内容相对很简单,但是自己还是花费了很久才完成。
经过这次实验,自己又重新熟悉了Keil-2软件,并且学习了利用仿真功能验证程序的功能。
以前51单片机编程用的都是汇编,这次经过两个简单的C语言环境下的实验也初步掌握了C编程的框架和注意事项,收获蛮大的。
实验二液晶显示程序设计
一、实验目的:
掌握C8051单片机液晶显示程序设计方法。
二、实验任务:
1.设计并调试一个显示程序,利用所提供液晶显示器滚动显示123456这六个数字,并以每字符500毫秒的速度向右移动循环。
2.实现秒表计时功能。
用键盘产生中断控制秒表的开始和停止。
三、实验代码及运行结果
A.实验任务1对应的程序代码及结果:
1.程序设计分析及源代码:
在主程序中已经完成了液晶显示的初始化,我们只要完成液晶显示器的清屏,并调用显示数字程序完成各个数字的轮流显示,调用LCDC_DisFull(Clr)后,可以使液晶显示器清屏,为123456的轮流显示创造环境,延迟500毫秒后调用LCDC_DispWord显示子程序显示123456,延迟500毫秒后,清屏,6个数字顺次向右移动一位,直到屏幕最右侧,然后再从最左侧开始新一轮的显示,这样就完成了123456的轮流显示,程序代码如下:
#include"main.h"//引用外部头文件
/*****************************主循环程序****************************/
inti=0;
voidmain(void)
{
//禁止看门狗定时器
WDTCN=0xde;
WDTCN=0xad;
//初始化
SYSCLK_Init();
PORT_Init();
Key_Init();
LCDC_Init();
LCDC_DisFull(Full);
Delay_ms(500);
LCDC_DisFull(Clr);//清屏
Delay_ms(500);//延时500ms,准备显示数字
//循环显示数字
while
(1)
{
LCDC_DispWord((i+0)%120,3,WLib_1_4x8,1,4,1);
LCDC_DispWord((i+8)%120,3,WLib_2_5x8,1,5,1);
LCDC_DispWord((i+16)%120,3,WLib_3_5x8,1,5,1);
LCDC_DispWord((i+24)%120,3,WLib_4_6x8,1,6,1);
LCDC_DispWord((i+32)%120,3,WLib_5_5x8,1,5,1);
LCDC_DispWord((i+40)%120,3,WLib_6_5x8,1,5,1);
Delay_ms(500);//延时500ms
LCDC_DisFull(Clr);//清屏
i=i+4;//向右循环4个单元
}
}
/*******************************程序结束*****************************/
2.程序运行结果:
程序运行后可以在LCD屏上显示1234556的循环显示如下图:
B.实验任务2对应的程序代码及结果:
1.程序设计分析及源代码:
在主程序中已经完成了液晶显示的初始化,我们只要完成液晶显示器的清屏,先使高位显示为0,低位从0开始按01234567890的顺序显示,没显示完一遍后高位加1,当高位加到6后,使高位变为0,从0开始完成0123450的高位显示,这样高低位结合边实现了从0到59的轮流显示;在程序中秒表的高位和低位显示都是在循环的条件下完成的,每当低位完成依次9到0的转换,就使高位i加1,然后判断i的大小,完成高位的显示,若i等于6,则将i转换为0,分钟的低位加1,依次下去显示,即完成了秒表功能,程序如下:
#include"main.h"
unsignedcharkey;//定义键值变量
/****************************主循环程序******************************/
intidatax;
intidatay;
intidatai;
intidataj;
intidatak;
intidataz;
intidataflag;
voiddisp(k,z)
{
if(z==0)LCDC_DispWord(34+k,4,WLib_0_5x8,1,5,1);
if(z==1)LCDC_DispWord(34+k,4,WLib_1_4x8,1,5,1);
if(z==2)LCDC_DispWord(34+k,4,WLib_2_5x8,1,5,1);
if(z==3)LCDC_DispWord(34+k,4,WLib_3_5x8,1,6,1);
if(z==4)LCDC_DispWord(34+k,4,WLib_4_6x8,1,5,1);
if(z==5)LCDC_DispWord(34+k,4,WLib_5_5x8,1,5,1);
if(z==6)LCDC_DispWord(34+k,4,WLib_6_5x8,1,5,1);
if(z==7)LCDC_DispWord(34+k,4,WLib_7_5x8,1,5,1);
if(z==8)LCDC_DispWord(34+k,4,WLib_8_5x8,1,5,1);
if(z==9)LCDC_DispWord(34+k,4,WLib_9_5x8,1,5,1);
}
voidmain(void)
{//禁止看门狗定时器
WDTCN=0xde;
WDTCN=0xad;
//初始化
SYSCLK_Init();
PORT_Init();
Key_Init();
LCDC_Init();
LCDC_DisFull(Full);
Delay_ms(500);
LCDC_DisFull(Clr);
Delay_ms(500);
x=0;
y=0;
i=0;
j=0;//初始化秒表,分钟和秒以及毫秒的显示都为0
while
(1)
{
disp(6,x);
disp(12,y);
LCDC_DispWord(52,4,WLib_line_6x8,1,6,1);
disp(24,i);
disp(30,j);
if(flag==1)//键盘摁下1键,秒表启动
{
Delay_s
(1);//延时1s,加1
j++;
if(j==10)//到第10s时,低位清0,高位加1
{i++;j=0;}
if(i==6)
{i=0;
y++;//到秒的高位为6时,高位清0
if(y==10)
{x++;y=0;}//当秒加到60时,分钟位加1,秒位全部清0
}
}
key=GetKey();//调用键盘扫描函数,返回的键值送变量key
if(key!
=0xFF)
{
Delay_ms(50);
switch(key)//键值有效执行按键程序
{
case0x01:
{flag=1;}//摁下1键,秒钟开始运行
break;
case0x02:
{flag=0;i=0;j=0;x=0;y=0;}//摁下2键,秒表清0
break;
case0x03:
{flag=0;}//摁下3键,秒表暂停
break;
}
}
}
}
/*****************************文件结束*******************************/
2.程序运行结果:
程序运行后可以看到秒表在LCD上运行的界面如下图:
四、实验总结
以前没有学习过LCD显示屏幕的使用,刚开始感觉比较难,但是在师兄的指导下,感觉在C环境下的编程还是不太难。
在任务一中,自己刚开始使用for循环让数据滚动,但总会出现中间停滞的不稳定现象,后分析是因为LCD屏幕是128位,利用for循环容易造成数据显示不全和错位的状况,所以在师兄推荐下改用while循环直接累加右移,这样避免了刚才的状况;对应实验二,最开始时候disp显示程序自己分别使用了disp_h、disp_m、disp_s三个程序分别时分秒部分,后来师兄指出这样比较浪费存储器空间,自己就修改为最终的disp(k,z)这样的程序,把时分秒显示压缩为一个子程序,效果比较好。
实验三串行通讯程序设计
一、实验目的:
掌握C8051单片机串行通讯程序设计方法。
二、实验任务:
设计并调试一个串行通讯程序,利用单片串行端口将片外RAM中以3000H为起始地址的1024个字节通过串行发送端口A输出,并以自闭环的形式由串行接收口B接收,并存储到以4000H为起始地址的空间中。
三、实验代码及运行结果
1.程序设计分析及源代码:
先完成程序的初始化,然后进行数据的接受,在判断发送数据的条件,若满足则进行数据的发送,若不满足,则提前结束程序的运行。
程序运行后,从0x30开始和0x40开始的1024个单元中数据为随机数且相等。
停止程序的运行,以0x30为首地址的1024个单元中的数据变为i%255,继续运行程序,此时以0x40为首地址的1024个单元中数据变为i%255。
程序如下:
/*******************************************************************/
#include"main.h"
/**************主循环程序*********************/
voidmain(void)
{
unsignedchartable[]={0x20,0x21,0x22,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x40,0x41,0x42,0x43,0x44,0x45};
unsignedcharxdata*temp0;
unsignedchartemp;
unsignedcharxdata*temp1;
unsignedinti,k;
WDTCN=0xDE;//禁止看门狗定时器
WDTCN=0xAD;
//初试化程序
SYSCLK_Init();
PORT_Init();
Uart0_Init(BaudRate_115200);
Uart1_Init(BaudRate_115200);
temp0=0x3000;
temp1=0x4000;
k=0;
//初试化结束
for(i=0;i<255;i++)//给发送的数据赋值
{
*temp0=i%255;//依次给temp指针对应空间赋i%255
temp0++;
}
while
(1)
{
Uart0_SendByte(*temp0);
Delay_ms(5);
temp=Uart1_ReceiveData();//串口1接收的数据
Delay_ms(5);
if(temp!
=0xff&&k<1024)//串口0接收的数据是否有效
{//有效Uart0将接收的数据发送出去
*temp1=temp;
k++;
temp1++;
temp0++;
}
}
}
/***************文件结束****************************/
2.程序运行结果:
这段程序运行虽然使用了串口,但是具体数值的读取和判断还需要从Keil-2里面的仿真模块,输入说要看的单元地址分别查看0x3000的内容,由于我们设置的为循环赋为i%255,所以运行结果截图如下图3-1与图3-2所示:
图3-1以0x3000为首地址的内存数据显示
同样利用仿真功能查看0x4000空间后面所对应的数据结果如下图3-2所示:
图3-2以0x4000为首地址的内存数据显示
四、实验总结
这是自己做的第三个实验,并且这个实验相对比较简单,只需用将原来的程序加以修改一点点就能完成最终的实验任务。
通过这次实验,自己对51单片机串口通信的基本模式有了初步的了解,实验虽然简单,但是十分实用。
实验四A/D转换实验
一、实验目的:
掌握C8051单片机A/D转换和时钟中断的程序设计方法。
二、实验任务:
设计并调试一个A/D采样程序,使用外部22.1184MHz晶振。
利用定时器中断,每1秒钟中断一次并采样。
采样AIN0,1和温度通道信号,并在LCD上显示其电压和温度值。
通过手动调节VR2电位器,观察电压值的变化。
三、实验代码及运行结果
1.程序设计分析及源代码:
先完成程序的初始化,然后开启中断,从通道0和通道1读取电压值,通道2读取芯片温度值,并显示在LCD上,代码如下:
/********************************************************************/
#include"main.h"
/****************************主循环程序*****************************/
voidmain(void)
{
unsignedlongvoltage;//电压值(毫伏)
unsignedlongtp;
inti;//循环计数器
WDTCN=0xde;
WDTCN=0xad;
SYSCLK_Init();//系统时钟初始化
PORT_Init();//系统端口初始化
LCDC_Init();//LCD初始化
Timer3_Init(SYSCLK/SAMPLERATE0);//初始化Timer3溢出的值
ADC0_Init();//ADC初始化
LCDC_DisFull(Full);//满屏
LCDC_DisFull(Clr);//清屏
ADC0_enable
(1);//ADC0使能
LCDC_DisFull(Clr);//清屏
while
(1)
{
Delay_ms(500);
for(i=0;i<9;i++)//ADC0九个通道
{
Delay_ms(100);
DISABLE_INTERRUPTS;//关闭中断
voltage=ADC_Valud_Return(i);//给全局变量赋ADC的值
ENABLE_INTERRUPTS;//重新开启中断
voltage=voltage*VREF0;//实际电压
DISABLE_INTERRUPTS;//关中断
switch(i)
{
case0:
//通道0显示
LCDC_DispWord(0,48,WLib_tong_16x16,2,16,1);
LCDC_DispWord(16,48,WLib_dao_16x16,2,16,1);
LCDC_DispWord(32,48,&WLib_Num_8x16[i*32],2,8,1);
LCDC_DispWord(40,48,WLib_maohao_8x16,2,8,1);
LCDC_DispWord(112,48,WLib_fu_16x16,2,16,1);
voltage=voltage>>16;
if(voltage>0x0004E2)
{
voltage=8*(voltage-0x0004E2);
LCDC_DispWord(48,48,&WLib_Num_8x16[0],2,8,1);
LCDC_DispWord(56,48,&WLib_Num_8x16[voltage/10000*16],2,8,1);
LCDC_DispWord(64,48,&WLib_Num_8x16[voltage/1000*16],2,8,1);
LCDC_DispWord(72,48,WLib_dian_8x16,2,8,1);
LCDC_DispWord(80,48,&WLib_Num_8x16[voltage%1000/100*16],2,8,1);
LCDC_DispWord(88,48,&WLib_Num_8x16[voltage%100%100/10*16],2,8,1);
LCDC_DispWord(96,48,&WLib_Num_8x16[voltage%100%100%10*16],2,8,1);
}
else
{
voltage=8*(0x0004E2-voltage);LCDC_DispWord(48,48,&WLib_Num_8x16[160],2,8,1);
LCDC_DispWord(56,48,&WLib_Num_8x16[voltage/10000*16],2,8,1);
LCDC_DispWord(64,48,&WLib_Num_8x16[voltage/1000*16],2,8,1);
LCDC_DispWord(72,48,WLib_dian_8x16,2,8,1);
LCDC_DispWord(80