4.29日接手了为导师修改论文的任务,由于论文非本专业,因此过程较为痛苦。改改停停,玩玩等等,以致延误日久。至7.7日暂时交差,算是暂时告一段落。
7月将小论文写好投至一非核心普通学术期刊,已经接收,预计8月可发表。算是完成了一个毕业所必需的硬性要求。
自7.15号回家,至8.1号基本上都在家里玩,从8.2日才开始恢复学习。
昨日看了郭天祥单片机C51语言的第一讲,感觉很不错(郭天祥单片机教程在线学习地址:在ku6.com里搜索“keil单片机视频教程”专辑即可找到)。但以前的一些东西忘了一些,因此今天又看了一下电容知识、去耦、整流滤波、74LS373锁存器、高阻态等相关内容。并写了一个简单的发光二极管小程序,如下:
#include
void delay();
void led1();
void led2();
void led3();
void main()
{
while(1)
{
led1();
delay();
led3();
delay();
led2();
delay();
led3();
delay();
}
}
void led1()
{
P2=0xaa;
}
void delay()
{
unsigned int a,b;
for(a=0;a<1000;a++)
for(b=0;b<200;b++);
}
void led2()
{
P2=0x55;
}
void led3()
{
P2=0xff;
}
晚上看了一小部分郭天祥单片机C51语言的第二讲,感觉对keil软件的调试和使用还有一些不熟悉的地方,明天的任务是听完第二讲,并将与该讲相关的不明白之处搞懂。
【08.8.4】较为精确地控制延时时间
今天看完了郭天祥单片机的第二讲,主要内容是学习延时程序的写法、子程序(带参数和不带参数的)调用、驱动蜂鸣器和继电器等。
学习的过程中,对机器周期、晶振、时钟周期和指令周期的概念又模糊了,在网上查了一下,先摘录如下:
单片机中为何要用晶振?
简单地说,没有晶振,就没有时钟周期,没有时钟周期,就无法执行程序代码,单片机就无法工作。
单片机工作时,是一条一条地从RoM中取指令,然后一步一步地执行。单片机访问一次存储器的时间,称之为一个机器周期,这是一个时间基准。—个机器周期包括 12个时钟周期。如果一个单片机选择了12MHz晶振,它的时钟周期是1/12us,它的一个机器周期是12×(1/12)us,也就是1us。
MCS —51单片机的所有指令中,有一些完成得比较快,只要一个机器周期就行了,有一些完成得比较馒,得要2个机器周期,还有两条指令要4个机器周期才行。为了衡量指令执行时间的长短,又引入一个新的概念:指令周期。所谓指令周期就是指执行一条指令的时间。例如,当需要计算DJNZ指令完成所需要的时间时,首先必须要知道晶振的频率,设所用晶振为12MHz,则一个机器周期就是1us。而DJNZ指令是双周期指令,所以执行一次要2us。如果该指令需要执行 500次,正好1000us,也就是1ms。
机器周期不仅对于指令执打有着重要的意义,而且机器周期也是单片机定时器和计数器的时间基准。例如一个单片机选择了12MHz晶振,那么当定时器的数值加1时,实际经过的时间就是1us,这就是单片机的定时原理
今天的一个主要收获是初步学会了用keil的软件仿真功能来较为精确地实现计时功能。另外还看了一下集电极开路的概念,但仍然对此迷迷糊糊。另外还学习了三极管在数字电路中如何充当电子开关的。
第二讲课后留了四个作业题,由于对keil仿真的揣摩花了较多时间,因此今天只做完一个。
题目2-1:
//程序功能:第一个发光管以间隔200ms闪烁
#include
sbit P2_0=P2^0;
void delay(unsigned int);
void led_on();
void led_off();
void main()
{
led_on();
delay(22200);//这里的22200是用keil软件仿真反复试凑多次得出的,基本满足200ms的近似值,差不多是200.296ms
led_off();
delay(22200);
}
void led_on()
{
P2_0=0;
}
void led_off()
{
P2_0=1;
}
void delay(unsigned int a)
{
while(a--);
}
程序在单片机开发板上已经运行通过,但是不是200ms肉眼就看不出来了,好像差不多吧……
【08.8.5】流水灯与蜂鸣器
【08.8.6】数码管、定时器与中断
【08.8.8】独立键盘与矩阵键盘
【08.8.9】A/D与D/A转换,遇到困难
【08.8.10】接触串口
【08.8.11】开发板上位机软件失灵?
【08.8.12】初识I2C总线
【08.8.13】I2C总线,初学不容易
【08.8.14】关注奥运多于mcu
【08.8.15】在看奥运,没学习
【08.8.30】写I2C程序与LCD1602程序
学习的过程中,对机器周期、晶振、时钟周期和指令周期的概念又模糊了,在网上查了一下,先摘录如下:
单片机中为何要用晶振?
简单地说,没有晶振,就没有时钟周期,没有时钟周期,就无法执行程序代码,单片机就无法工作。
单片机工作时,是一条一条地从RoM中取指令,然后一步一步地执行。单片机访问一次存储器的时间,称之为一个机器周期,这是一个时间基准。—个机器周期包括 12个时钟周期。如果一个单片机选择了12MHz晶振,它的时钟周期是1/12us,它的一个机器周期是12×(1/12)us,也就是1us。
MCS —51单片机的所有指令中,有一些完成得比较快,只要一个机器周期就行了,有一些完成得比较馒,得要2个机器周期,还有两条指令要4个机器周期才行。为了衡量指令执行时间的长短,又引入一个新的概念:指令周期。所谓指令周期就是指执行一条指令的时间。例如,当需要计算DJNZ指令完成所需要的时间时,首先必须要知道晶振的频率,设所用晶振为12MHz,则一个机器周期就是1us。而DJNZ指令是双周期指令,所以执行一次要2us。如果该指令需要执行 500次,正好1000us,也就是1ms。
机器周期不仅对于指令执打有着重要的意义,而且机器周期也是单片机定时器和计数器的时间基准。例如一个单片机选择了12MHz晶振,那么当定时器的数值加1时,实际经过的时间就是1us,这就是单片机的定时原理
今天的一个主要收获是初步学会了用keil的软件仿真功能来较为精确地实现计时功能。另外还看了一下集电极开路的概念,但仍然对此迷迷糊糊。另外还学习了三极管在数字电路中如何充当电子开关的。
第二讲课后留了四个作业题,由于对keil仿真的揣摩花了较多时间,因此今天只做完一个。
题目2-1:
//程序功能:第一个发光管以间隔200ms闪烁
#include
sbit P2_0=P2^0;
void delay(unsigned int);
void led_on();
void led_off();
void main()
{
led_on();
delay(22200);//这里的22200是用keil软件仿真反复试凑多次得出的,基本满足200ms的近似值,差不多是200.296ms
led_off();
delay(22200);
}
void led_on()
{
P2_0=0;
}
void led_off()
{
P2_0=1;
}
void delay(unsigned int a)
{
while(a--);
}
程序在单片机开发板上已经运行通过,但是不是200ms肉眼就看不出来了,好像差不多吧……
【08.8.5】流水灯与蜂鸣器
今天上午和中午做了第二讲剩余的三个课后作业。程序如下,已经在开发板上调试通过。
**********************************************************
题目2-2:
//8个发光管由上至下间隔500ms流动,亮灭的时间均为500ms,亮的时候同时蜂鸣器发声
#include
#include
sbit P3_4=P3^4;
void delay(unsigned int);
void beep_on();
void beep_off();
void main()
{
unsigned char a=0xfe; //为中间变量a赋初值
while(1) //发光管循环流动开始
{
P2=a; //将中间变量a的值赋给P2口
beep_on(); //灯亮的同时令蜂鸣器也发声
delay(55500); //499.732ms后,令灯和蜂鸣器关闭
P2=0xff;
beep_off();
delay(55500); //灯灭时间也为499.732ms
a=_crol_(a,1); //使a循环左移一位
}
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void beep_on() //令蜂鸣器发声,蜂鸣器由P3.4控制
{
P3_4=0;
}
void beep_off() //关闭蜂鸣器
{
P3_4=1;
}
**********************************************************
题目2-3:
//8个发光管来回流动,间隔100ms,亮时发声
#include
#include
sbit P3_4=P3^4;
void delay(unsigned int);
void beep_on();
void beep_off();
void main()
{
unsigned char c,d;
while(1) //发光管循环流动开始
{
unsigned char a=0xfe; //为中间变量a赋初值,准备正向流动
for(c=7;c>0;c--) //发光管正向移动
{
P2=a; //将中间变量a的值赋给P2口
beep_on(); //灯亮的同时令蜂鸣器也发声
delay(11200); //100.8ms后,令灯和蜂鸣器关闭
P2=0xff;
beep_off();
delay(11200); //灯灭时间也为100.8ms
a=_crol_(a,1); //使a循环左移一位
}
for(d=7;d>0;d--) //发光管反向移动
{
P2=a;
beep_on();
delay(11200);
P2=0xff;
beep_off();
delay(11200);
a=_cror_(a,1); //使a循环右移一位
}
}
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void beep_on() //令蜂鸣器发声,蜂鸣器由P3.4控制
{
P3_4=0;
}
void beep_off() //关闭蜂鸣器
{
P3_4=1;
}
**********************************************************
题目2-4:
//8个发光管间隔200ms由上至下,再由下至上,再由上至下,再由下至上
//然后全部熄灭再以300ms间隔全部闪烁5次。重复上面过程
#include
#include
sbit P3_4=P3^4;
void led_turn();
void led_glitter();
void delay(unsigned int);
void main()
{
P2=0XFF; //使灯全部熄灭
delay(22200); //熄灭后再延时200ms
led_turn(); //令流水灯由上至下,再由下至上循环
led_turn(); //令流水灯由上至下,再由下至上循环
P2=0XFE; //点亮最后一轮循环中剩下的那一盏灯
delay(22200);
P2=0XFF; //使灯全部熄灭
delay(22200); //熄灭后再延时200ms
led_glitter(); //全部发光管以300ms间隔闪烁5次
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void led_turn() //令流水灯由上至下,再由下至上循环的函数
{
unsigned char c,d;
unsigned char a=0xfe; //为中间变量a赋初值,准备正向流动
for(c=7;c>0;c--) //发光管正向移动
{
P2=a; //将中间变量a的值赋给P2口
delay(22300); //200ms后,令灯和蜂鸣器关闭
P2=0xff;
delay(22300); //灯灭时间也为200ms
a=_crol_(a,1); //使a循环左移一位
}
for(d=7;d>0;d--) //发光管反向移动
{
P2=a;
delay(22300);
P2=0xff;
delay(22300);
a=_cror_(a,1); //使a循环右移一位
}
}
void led_glitter() //全部发光管以300ms间隔闪烁5次
{
unsigned char e=5;
while(e--) //循环5次
{
P2=0xff; //全部熄灭
delay(33300);
P2=0x00; //全部点亮
delay(33300);
}
}
**********************************************************
下午和晚上看了郭天祥C51单片机教程第三讲,主要讲了数码管的静态显示,以及中断的概念与简单应用。数码管和中断的控制涉及到了一些寄存器和芯片管脚的控制,看过视频之后,感觉会似乎是会了,但是记得并不牢靠,总是有些模模糊糊。虽然课后没有留作业题,但明天也打算做一系列的试验来巩固一下,否则不趁热打铁的话,很快就会忘掉了。
**********************************************************
题目2-2:
//8个发光管由上至下间隔500ms流动,亮灭的时间均为500ms,亮的时候同时蜂鸣器发声
#include
#include
sbit P3_4=P3^4;
void delay(unsigned int);
void beep_on();
void beep_off();
void main()
{
unsigned char a=0xfe; //为中间变量a赋初值
while(1) //发光管循环流动开始
{
P2=a; //将中间变量a的值赋给P2口
beep_on(); //灯亮的同时令蜂鸣器也发声
delay(55500); //499.732ms后,令灯和蜂鸣器关闭
P2=0xff;
beep_off();
delay(55500); //灯灭时间也为499.732ms
a=_crol_(a,1); //使a循环左移一位
}
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void beep_on() //令蜂鸣器发声,蜂鸣器由P3.4控制
{
P3_4=0;
}
void beep_off() //关闭蜂鸣器
{
P3_4=1;
}
**********************************************************
题目2-3:
//8个发光管来回流动,间隔100ms,亮时发声
#include
#include
sbit P3_4=P3^4;
void delay(unsigned int);
void beep_on();
void beep_off();
void main()
{
unsigned char c,d;
while(1) //发光管循环流动开始
{
unsigned char a=0xfe; //为中间变量a赋初值,准备正向流动
for(c=7;c>0;c--) //发光管正向移动
{
P2=a; //将中间变量a的值赋给P2口
beep_on(); //灯亮的同时令蜂鸣器也发声
delay(11200); //100.8ms后,令灯和蜂鸣器关闭
P2=0xff;
beep_off();
delay(11200); //灯灭时间也为100.8ms
a=_crol_(a,1); //使a循环左移一位
}
for(d=7;d>0;d--) //发光管反向移动
{
P2=a;
beep_on();
delay(11200);
P2=0xff;
beep_off();
delay(11200);
a=_cror_(a,1); //使a循环右移一位
}
}
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void beep_on() //令蜂鸣器发声,蜂鸣器由P3.4控制
{
P3_4=0;
}
void beep_off() //关闭蜂鸣器
{
P3_4=1;
}
**********************************************************
题目2-4:
//8个发光管间隔200ms由上至下,再由下至上,再由上至下,再由下至上
//然后全部熄灭再以300ms间隔全部闪烁5次。重复上面过程
#include
#include
sbit P3_4=P3^4;
void led_turn();
void led_glitter();
void delay(unsigned int);
void main()
{
P2=0XFF; //使灯全部熄灭
delay(22200); //熄灭后再延时200ms
led_turn(); //令流水灯由上至下,再由下至上循环
led_turn(); //令流水灯由上至下,再由下至上循环
P2=0XFE; //点亮最后一轮循环中剩下的那一盏灯
delay(22200);
P2=0XFF; //使灯全部熄灭
delay(22200); //熄灭后再延时200ms
led_glitter(); //全部发光管以300ms间隔闪烁5次
}
void delay(unsigned int b) //延时函数
{
while(b--);
}
void led_turn() //令流水灯由上至下,再由下至上循环的函数
{
unsigned char c,d;
unsigned char a=0xfe; //为中间变量a赋初值,准备正向流动
for(c=7;c>0;c--) //发光管正向移动
{
P2=a; //将中间变量a的值赋给P2口
delay(22300); //200ms后,令灯和蜂鸣器关闭
P2=0xff;
delay(22300); //灯灭时间也为200ms
a=_crol_(a,1); //使a循环左移一位
}
for(d=7;d>0;d--) //发光管反向移动
{
P2=a;
delay(22300);
P2=0xff;
delay(22300);
a=_cror_(a,1); //使a循环右移一位
}
}
void led_glitter() //全部发光管以300ms间隔闪烁5次
{
unsigned char e=5;
while(e--) //循环5次
{
P2=0xff; //全部熄灭
delay(33300);
P2=0x00; //全部点亮
delay(33300);
}
}
**********************************************************
下午和晚上看了郭天祥C51单片机教程第三讲,主要讲了数码管的静态显示,以及中断的概念与简单应用。数码管和中断的控制涉及到了一些寄存器和芯片管脚的控制,看过视频之后,感觉会似乎是会了,但是记得并不牢靠,总是有些模模糊糊。虽然课后没有留作业题,但明天也打算做一系列的试验来巩固一下,否则不趁热打铁的话,很快就会忘掉了。
【08.8.6】数码管、定时器与中断
今天做了三个实验来巩固第三讲的内容,主要练习了对数码管、定时器,以及中断(包括定时器中断和外部中断)的使用。以下三个程序均在实验板上调试通过。
**********************************************************
题3-1:
//使第6号数码管从0到F循环,然后令2号数码管显示“c”字符,重复此过程
#include
void delay(unsigned int);
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //0-F的编码,加code字段使其保存在程序存储区
void main()
{
unsigned int a;
P1=0X06; //使得6号数码管位选为1,管为共阴极接法
for(a=0;a<16;a++)
{
P2=num[a];
delay(35000);
}
P1=0X02; //将2号数码管的位选置为1
P2=0X58; //显示“c”字符
delay(35000);
}
void delay(unsigned int c)
{
while(c--);
}
**********************************************************
题3-2:
//数码管数值每隔1s加1,从0-F循环。每循环1轮后蜂鸣器响1下
//该程序要求使用定时器精确定时,并使用中断
#include
sbit P3_4=P3^4; //蜂鸣器用P3.4控制
unsigned char b,c;
void delay();
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void main()
{
EA=1; //打开总中断开关
ET1=1; //打开定时/计数器1中断开关
TMOD=0X10; //T1工作在方式1
TH1=0X3C; //3CB0=15536=65536-50000,此处装入定时初始值
TL1=0XB0; //此句与上一句也可写在delay函数定义中
P1=0X00; //选择第0位数码管作为显示
for(b=0;b<16;b++)
{
P2=num[b]; //将对应的编码赋给P2口
if(b==0) //每次循环一轮后蜂鸣器响一下
{
P3_4=0;
delay(); //如果0-f已经轮了一圈,则响一声
P3_4=1;
}
else
delay(); //否则正常延时
}
}
void etx0() interrupt 3 //响应定时/计数器1的中断
{
TH1=0X3C; //重新装入初始值
TL1=0XB0;
c++; //每产生一次中断,说明又过了一个50ms,c值加1
}
void delay() //延时1秒钟
{
TR1=1; //延时开始时,启动定时器
while(c<20); //若不积满20个延时周期,则空转耗时
c=0; //一旦到了20个周期,说明已经延时够了1s,则将c清零,备下次用
TR1=0; //并将定时器也关闭,等待下一次延时再开启
}
**********************************************************
题3-3:
//数码管初始显示F,当给一个外部中断后改为t,再次外部中断后再改为F
#include
bit a=0;
unsigned char code ft[]=
{0x71,/*F*/
0x78/*t*/}; //编码:第一个是F,第二个是t
void main()
{
EA=1; //打开中断总开关
EX1=1; //打开外部中断1
IT1=1; //设置外部中断1为边沿触发方式
P1=0X00; //使用第0号数码管
while(1)
{
P2=ft[a]; //切换F与t
}
}
void switch_word() interrupt 2 //外部中断1触发时,a在0、1之间切换
{
a=~a;
}
**********************************************************
其中题3-3需要用一根铁丝把P3.3引脚(外部中断1)连接到板子上的一个低电平(接地)上,给一个中断信号。不过实验过程中发现,只是用手拿着铁丝的一端,把铁丝的另一端连到P3.3引脚上,似乎也能引发外部中断。
晚上抽空看了中国军团奥运会的首次亮相,中国女足在场面上不占优势的情况下,2:1艰难战胜小组最强的对手瑞典队,出线形势一片大好。希望这场开门红也能预示着中国奥运代表团的好运吧。
明晚中国男足也要出场了,据说对手新西兰比较弱,国奥可能会取得历史的突破。不过中国男子足球向来都是给人以失望的多,明晚看看吧。
明天的学习计划:看郭天祥单片机第四讲。
**********************************************************
题3-1:
//使第6号数码管从0到F循环,然后令2号数码管显示“c”字符,重复此过程
#include
void delay(unsigned int);
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //0-F的编码,加code字段使其保存在程序存储区
void main()
{
unsigned int a;
P1=0X06; //使得6号数码管位选为1,管为共阴极接法
for(a=0;a<16;a++)
{
P2=num[a];
delay(35000);
}
P1=0X02; //将2号数码管的位选置为1
P2=0X58; //显示“c”字符
delay(35000);
}
void delay(unsigned int c)
{
while(c--);
}
**********************************************************
题3-2:
//数码管数值每隔1s加1,从0-F循环。每循环1轮后蜂鸣器响1下
//该程序要求使用定时器精确定时,并使用中断
#include
sbit P3_4=P3^4; //蜂鸣器用P3.4控制
unsigned char b,c;
void delay();
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void main()
{
EA=1; //打开总中断开关
ET1=1; //打开定时/计数器1中断开关
TMOD=0X10; //T1工作在方式1
TH1=0X3C; //3CB0=15536=65536-50000,此处装入定时初始值
TL1=0XB0; //此句与上一句也可写在delay函数定义中
P1=0X00; //选择第0位数码管作为显示
for(b=0;b<16;b++)
{
P2=num[b]; //将对应的编码赋给P2口
if(b==0) //每次循环一轮后蜂鸣器响一下
{
P3_4=0;
delay(); //如果0-f已经轮了一圈,则响一声
P3_4=1;
}
else
delay(); //否则正常延时
}
}
void etx0() interrupt 3 //响应定时/计数器1的中断
{
TH1=0X3C; //重新装入初始值
TL1=0XB0;
c++; //每产生一次中断,说明又过了一个50ms,c值加1
}
void delay() //延时1秒钟
{
TR1=1; //延时开始时,启动定时器
while(c<20); //若不积满20个延时周期,则空转耗时
c=0; //一旦到了20个周期,说明已经延时够了1s,则将c清零,备下次用
TR1=0; //并将定时器也关闭,等待下一次延时再开启
}
**********************************************************
题3-3:
//数码管初始显示F,当给一个外部中断后改为t,再次外部中断后再改为F
#include
bit a=0;
unsigned char code ft[]=
{0x71,/*F*/
0x78/*t*/}; //编码:第一个是F,第二个是t
void main()
{
EA=1; //打开中断总开关
EX1=1; //打开外部中断1
IT1=1; //设置外部中断1为边沿触发方式
P1=0X00; //使用第0号数码管
while(1)
{
P2=ft[a]; //切换F与t
}
}
void switch_word() interrupt 2 //外部中断1触发时,a在0、1之间切换
{
a=~a;
}
**********************************************************
其中题3-3需要用一根铁丝把P3.3引脚(外部中断1)连接到板子上的一个低电平(接地)上,给一个中断信号。不过实验过程中发现,只是用手拿着铁丝的一端,把铁丝的另一端连到P3.3引脚上,似乎也能引发外部中断。
晚上抽空看了中国军团奥运会的首次亮相,中国女足在场面上不占优势的情况下,2:1艰难战胜小组最强的对手瑞典队,出线形势一片大好。希望这场开门红也能预示着中国奥运代表团的好运吧。
明晚中国男足也要出场了,据说对手新西兰比较弱,国奥可能会取得历史的突破。不过中国男子足球向来都是给人以失望的多,明晚看看吧。
明天的学习计划:看郭天祥单片机第四讲。
【08.8.7】数码管动态扫描——秒表设计
今天中午看了郭天祥单片机第四讲,内容主要是加深对中断和定时器的理解,以及数码管动态扫描的内容。下午及晚上做了两个程序练习,并已经在开发板上调试通过。程序如下:
**********************************************************
题4-1:
//利用动态扫描方法在六位数码管上显示出稳定的76543210
#include
void delay(unsigned char);
unsigned char code duan_num[]={ //数码管段选0-7编码
0x3F,/*0*/ 0x06,/*1*/ 0x5B,/*2*/ 0x4F,/*3*/
0x66,/*4*/ 0x6D,/*5*/ 0x7D,/*6*/ 0x07 /*7*/};
unsigned char code wei_num[]={ //数码管位选编码
0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00};
void main()
{
char b=7; //这里不能用unsigned char,否则会导致b减到0后不变为负数,而是变为256
for(b=7;b>=0;b--)
{
P2=0X00; //防止数码管出现余辉
P1=wei_num[b]; //位选赋值
P2=duan_num[b]; //段选赋值
delay(20);
}
}
void delay(unsigned char a)
{
while(a--);
}
**********************************************************
题4-2:
//用动态扫描方法和定时器1在数码管的后三位显示出秒表,精确到0.01秒,一直循环下去
//后两位显示到小数点后的0.01秒级别,前面一位显示秒
#include
void delay();
void display(unsigned char,unsigned char,unsigned char);
unsigned int b,num; //num记百分之一秒的个数
unsigned char code duan_num[]={ //段选0-9编码
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char code wei_num[]={0x05,0x06,0x07}; //位选编码,顺序由高位到低位
void main()
{
EA=1;
ET1=1;
TMOD=0x10;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
TR1=1;
while(1)
{
if(num==1000) //如果超过了量程,则将num清零
num=0;
display(num/100,num%100/10,num%10);
}
num=0; //记满1000个0.01s后,重新归零
}
void display(unsigned char second,unsigned char second0_1,unsigned char second0_01)
{
//百分秒位显示
P2=0X00;
P1=wei_num[2];
P2=duan_num[second0_01];
delay();
//十分秒位显示
P2=0X00;
P1=wei_num[1];
P2=duan_num[second0_1];
delay();
//秒位显示
P2=0X00;
P1=wei_num[0];
P2=duan_num[second]+0x80; //加0x80的目的:秒位后面应有小数点
delay();
}
void etx1() interrupt 3
{
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
num++;
}
void delay()
{
unsigned char c=200;
while(c--);
}
**********************************************************
题4-2中的delay()如果时间过短的话,将会导致写在前面的两位显示(百分秒位和十分秒位)亮度不够。
今天下午看完整个第四讲之后写程序的时候,觉得有些生疏。看来以后或许应该看一部分视频讲座,做一个程序练习题。这样可能印象会深刻一些吧。
今天晚上看了中国男子国奥队对新西兰的最后二十分钟的比赛,1:1的结果基本宣告了男足的出局。面对后面的比利时和巴西,恐怕没有多少人会奢望中国队在此后的两场比赛中能拿到分。
明天晚上就是万众瞩目的第29届奥运会的开幕式了,期待中……
明天的学习任务是看郭天祥单片机讲座第五章。
**********************************************************
题4-1:
//利用动态扫描方法在六位数码管上显示出稳定的76543210
#include
void delay(unsigned char);
unsigned char code duan_num[]={ //数码管段选0-7编码
0x3F,/*0*/ 0x06,/*1*/ 0x5B,/*2*/ 0x4F,/*3*/
0x66,/*4*/ 0x6D,/*5*/ 0x7D,/*6*/ 0x07 /*7*/};
unsigned char code wei_num[]={ //数码管位选编码
0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00};
void main()
{
char b=7; //这里不能用unsigned char,否则会导致b减到0后不变为负数,而是变为256
for(b=7;b>=0;b--)
{
P2=0X00; //防止数码管出现余辉
P1=wei_num[b]; //位选赋值
P2=duan_num[b]; //段选赋值
delay(20);
}
}
void delay(unsigned char a)
{
while(a--);
}
**********************************************************
题4-2:
//用动态扫描方法和定时器1在数码管的后三位显示出秒表,精确到0.01秒,一直循环下去
//后两位显示到小数点后的0.01秒级别,前面一位显示秒
#include
void delay();
void display(unsigned char,unsigned char,unsigned char);
unsigned int b,num; //num记百分之一秒的个数
unsigned char code duan_num[]={ //段选0-9编码
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char code wei_num[]={0x05,0x06,0x07}; //位选编码,顺序由高位到低位
void main()
{
EA=1;
ET1=1;
TMOD=0x10;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
TR1=1;
while(1)
{
if(num==1000) //如果超过了量程,则将num清零
num=0;
display(num/100,num%100/10,num%10);
}
num=0; //记满1000个0.01s后,重新归零
}
void display(unsigned char second,unsigned char second0_1,unsigned char second0_01)
{
//百分秒位显示
P2=0X00;
P1=wei_num[2];
P2=duan_num[second0_01];
delay();
//十分秒位显示
P2=0X00;
P1=wei_num[1];
P2=duan_num[second0_1];
delay();
//秒位显示
P2=0X00;
P1=wei_num[0];
P2=duan_num[second]+0x80; //加0x80的目的:秒位后面应有小数点
delay();
}
void etx1() interrupt 3
{
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
num++;
}
void delay()
{
unsigned char c=200;
while(c--);
}
**********************************************************
题4-2中的delay()如果时间过短的话,将会导致写在前面的两位显示(百分秒位和十分秒位)亮度不够。
今天下午看完整个第四讲之后写程序的时候,觉得有些生疏。看来以后或许应该看一部分视频讲座,做一个程序练习题。这样可能印象会深刻一些吧。
今天晚上看了中国男子国奥队对新西兰的最后二十分钟的比赛,1:1的结果基本宣告了男足的出局。面对后面的比利时和巴西,恐怕没有多少人会奢望中国队在此后的两场比赛中能拿到分。
明天晚上就是万众瞩目的第29届奥运会的开幕式了,期待中……
明天的学习任务是看郭天祥单片机讲座第五章。
【08.8.8】独立键盘与矩阵键盘
今天看了郭天祥单片机视频的第五讲,主要内容是键盘的检测与控制。课后写了两个程序,第一个已经在实验板上通过,第二个由于一些原因,尚未调试成功。奥运会开幕式马上就要开始了,今天晚上不弄了,明天早上再详细研究。先只把第一个程序写上来:
**********************************************************
题5-1:
//按一下独立键盘,数码管的数加1,加到F后循环回0
#include
sbit key=P3^2; //独立键盘接在P3.2口上
unsigned char count;
void delay();
void display();
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void main()
{
P1=0X00; //选择第0号数码管作为本次程序显示之用
while(1)
{
if(key==0) //按键是否按下
{
delay(); //延时以去除抖动
if(key==0) //再次检测按键是否按下
{
count++;
if(count>=10)
count=0;
while(!key); //如果键盘按下还没松手,就一直等待
}
}
display();
}
}
void display()
{
P2=num[count];
}
void delay() //延时约10ms
{
unsigned char a=1110;
while(a--);
}
**********************************************************
上面的程序是独立键盘的使用,第五讲的另一个重要内容是矩阵键盘。关于矩阵键盘的检测,主要流程大体如下:
1、先扫描第一行,比如令第一行为低电平,给Px口赋值
2、把Px口的数值再读入一个临时变量temp中,如果第一行有键被按下,则此时的temp值定然不与Px相同,已经变化了。
3、把temp与0x0f(该数视具体硬件情况而定)相与后再赋给temp
4、判断新的temp是否等于0x0f,如不等,则说明有键被按下。
5、先去抖动后,用switch-case语句判断第一行具体是哪一个键被按下
6、其他行以此类推
题5-2中写了一个矩阵键盘的程序,但是今天尚未调试好,明天再说。
奥运会开幕式已经开始了!今天就先写到这儿吧。去看电视了~~~~
祝福中国!
**********************************************************
题5-1:
//按一下独立键盘,数码管的数加1,加到F后循环回0
#include
sbit key=P3^2; //独立键盘接在P3.2口上
unsigned char count;
void delay();
void display();
unsigned char code num[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void main()
{
P1=0X00; //选择第0号数码管作为本次程序显示之用
while(1)
{
if(key==0) //按键是否按下
{
delay(); //延时以去除抖动
if(key==0) //再次检测按键是否按下
{
count++;
if(count>=10)
count=0;
while(!key); //如果键盘按下还没松手,就一直等待
}
}
display();
}
}
void display()
{
P2=num[count];
}
void delay() //延时约10ms
{
unsigned char a=1110;
while(a--);
}
**********************************************************
上面的程序是独立键盘的使用,第五讲的另一个重要内容是矩阵键盘。关于矩阵键盘的检测,主要流程大体如下:
1、先扫描第一行,比如令第一行为低电平,给Px口赋值
2、把Px口的数值再读入一个临时变量temp中,如果第一行有键被按下,则此时的temp值定然不与Px相同,已经变化了。
3、把temp与0x0f(该数视具体硬件情况而定)相与后再赋给temp
4、判断新的temp是否等于0x0f,如不等,则说明有键被按下。
5、先去抖动后,用switch-case语句判断第一行具体是哪一个键被按下
6、其他行以此类推
题5-2中写了一个矩阵键盘的程序,但是今天尚未调试好,明天再说。
奥运会开幕式已经开始了!今天就先写到这儿吧。去看电视了~~~~
祝福中国!
【08.8.9】A/D与D/A转换,遇到困难
昨晚看了奥运会开幕式,有觉得不错的地方,也有一些败笔。不过总体上还是可以的,个人给打70分吧。今天看了女子举重、男子射击和女足的直播,中国在第一天产生的7枚金牌中,拿了2枚,暂居金牌榜第一位。
今天上午把昨晚没有弄出来的题5-2调试成功了,程序如下:
**********************************************************
题5-2:
//将4*4矩阵键盘分别对应0-F,按过一个键,则在数码管上显示对应的数值
#include
sbit key=P3^2; //独立键盘接在P3.2口上
unsigned char num; //num为数码管上显示的数值
void delay();
void display(unsigned char);
unsigned char scan();
unsigned char code table[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71,0x49}; //从0-F的数码管共阴极编码,最后一个是错误代码
void main()
{
P1=0X00; //选择第0号数码管作为本次程序显示之用
while(1)
{
display(scan());
}
}
void display(unsigned char a)
{
P2=table[a];
}
void delay() //延时约10ms
{
unsigned int b=1110;
while(b--);
}
unsigned char scan()
{
unsigned char temp;
/***********检测第一行是否有键按下,如有则为num赋相应值***********/
P0=0XEF; //令4*4键盘的第一行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第一行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第一行按键是否有键仍为按下
{
switch(temp) //具体判断第一行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=0;
break;
case 0x0d: num=1;
break;
case 0x0b: num=2;
break;
case 0x07: num=3;
break;
default: num=16;
}
while(P0!=0XEF); //如果键盘按下还没松手,就一直等待
} //注意:上一行不能误写成while(temp!=0x0f);这也是昨天调试失败的原因
}
/***********检测第二行是否有键按下,如有则为num赋相应值***********/
P0=0XdF; //令4*4键盘的第二行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第二行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第二行按键是否有键仍为按下
{
switch(temp) //具体判断第二行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=4;
break;
case 0x0d: num=5;
break;
case 0x0b: num=6;
break;
case 0x07: num=7;
break;
default: num=16;
}
while(P0!=0XdF); //如果键盘按下还没松手,就一直等待
}
}
/***********检测第三行是否有键按下,如有则为num赋相应值***********/
P0=0XbF; //令4*4键盘的第三行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第三行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第三行按键是否有键仍为按下
{
switch(temp) //具体判断第三行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=8;
break;
case 0x0d: num=9;
break;
case 0x0b: num=10;
break;
case 0x07: num=11;
break;
default: num=16;
}
while(P0!=0XbF); //如果键盘按下还没松手,就一直等待
}
}
/***********检测第四行是否有键按下,如有则为num赋相应值***********/
P0=0X7F; //令4*4键盘的第四行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第四行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第四行按键是否有键仍为按下
{
switch(temp) //具体判断第四行的哪二个键被按下,并给num赋予相应值
{
case 0x0e: num=12;
break;
case 0x0d: num=13;
break;
case 0x0b: num=14;
break;
case 0x07: num=15;
break;
default: num=16;
}
while(P0!=0X7F); //如果键盘按下还没松手,就一直等待
}
}
return num; //num为函数返回值
}
**********************************************************
今天看了郭天祥单片机的第六讲,主要是A/D和D/A转换的内容。不过自己的单片机开发板上没有D/A芯片,A/D芯片也和讲座中的不一样。想写一个程序试一下,但对ADC0831的管脚不了解。就下了一个说明书,但是是英文的,晚上也困了,懒得研究English了,明天再说吧。
今天上午把昨晚没有弄出来的题5-2调试成功了,程序如下:
**********************************************************
题5-2:
//将4*4矩阵键盘分别对应0-F,按过一个键,则在数码管上显示对应的数值
#include
sbit key=P3^2; //独立键盘接在P3.2口上
unsigned char num; //num为数码管上显示的数值
void delay();
void display(unsigned char);
unsigned char scan();
unsigned char code table[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71,0x49}; //从0-F的数码管共阴极编码,最后一个是错误代码
void main()
{
P1=0X00; //选择第0号数码管作为本次程序显示之用
while(1)
{
display(scan());
}
}
void display(unsigned char a)
{
P2=table[a];
}
void delay() //延时约10ms
{
unsigned int b=1110;
while(b--);
}
unsigned char scan()
{
unsigned char temp;
/***********检测第一行是否有键按下,如有则为num赋相应值***********/
P0=0XEF; //令4*4键盘的第一行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第一行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第一行按键是否有键仍为按下
{
switch(temp) //具体判断第一行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=0;
break;
case 0x0d: num=1;
break;
case 0x0b: num=2;
break;
case 0x07: num=3;
break;
default: num=16;
}
while(P0!=0XEF); //如果键盘按下还没松手,就一直等待
} //注意:上一行不能误写成while(temp!=0x0f);这也是昨天调试失败的原因
}
/***********检测第二行是否有键按下,如有则为num赋相应值***********/
P0=0XdF; //令4*4键盘的第二行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第二行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第二行按键是否有键仍为按下
{
switch(temp) //具体判断第二行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=4;
break;
case 0x0d: num=5;
break;
case 0x0b: num=6;
break;
case 0x07: num=7;
break;
default: num=16;
}
while(P0!=0XdF); //如果键盘按下还没松手,就一直等待
}
}
/***********检测第三行是否有键按下,如有则为num赋相应值***********/
P0=0XbF; //令4*4键盘的第三行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第三行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第三行按键是否有键仍为按下
{
switch(temp) //具体判断第三行的哪一个键被按下,并给num赋予相应值
{
case 0x0e: num=8;
break;
case 0x0d: num=9;
break;
case 0x0b: num=10;
break;
case 0x07: num=11;
break;
default: num=16;
}
while(P0!=0XbF); //如果键盘按下还没松手,就一直等待
}
}
/***********检测第四行是否有键按下,如有则为num赋相应值***********/
P0=0X7F; //令4*4键盘的第四行左端接通
temp=P0; //再用一个临时变量将P0信息读回
temp=temp&0x0f; //再把该临时变量与0x0f相与之后,赋给自身
if(temp!=0x0f) //一旦temp与0x0f不相等,则说明低四位必定已变,即第四行有按键被按下
{
delay(); //延时以去除抖动
if(temp!=0x0f) //延时之后,再次检测第四行按键是否有键仍为按下
{
switch(temp) //具体判断第四行的哪二个键被按下,并给num赋予相应值
{
case 0x0e: num=12;
break;
case 0x0d: num=13;
break;
case 0x0b: num=14;
break;
case 0x07: num=15;
break;
default: num=16;
}
while(P0!=0X7F); //如果键盘按下还没松手,就一直等待
}
}
return num; //num为函数返回值
}
**********************************************************
今天看了郭天祥单片机的第六讲,主要是A/D和D/A转换的内容。不过自己的单片机开发板上没有D/A芯片,A/D芯片也和讲座中的不一样。想写一个程序试一下,但对ADC0831的管脚不了解。就下了一个说明书,但是是英文的,晚上也困了,懒得研究English了,明天再说吧。
【08.8.10】接触串口
今天参考了一下开发板自带的程序,写了一个关于ADC0831的程序,在开发板上调试通过了。但是还是有些糊涂,看来开学之后需要在图书馆里借本关于单片机外围电路的书看一下,像这些常用的AD/DA芯片,还是不太熟悉。
**********************************************************
题6-1:
//利用ADC0831,调动电位器,使得数码管的显示数字变化
#include
sbit SCL=P1^3; //接ADC0831的SCL端
sbit SDA=P1^4; //接ADC0831的SDA端
sbit rst=P1^5; //接DS1302的CS端
sbit CS=P1^6; //接ADC0831的CS端
unsigned char num;
unsigned char code duan_num[]={ //段选0-9编码
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char code wei_num[]={0x05,0x06,0x07}; //位选编码,顺序由高位到低位
void delay(unsigned char);
void display(unsigned char,unsigned char,unsigned char);
unsigned char ADC_read();
void main()
{
unsigned char b=254;
rst=0; //屏蔽掉DS1302芯片,防止对本实验产生冲突
while(1)
{
b++;
if(b==255)
num=ADC_read();
display(num/100,num%100/10,num%10);
}
}
void delay(unsigned char a)
{
while(a--);
}
void display(unsigned char bai,unsigned char shi,unsigned char ge)
{
//个位显示
P2=0X00;
P1=wei_num[2];
P2=duan_num[ge];
delay(200);
//十位显示
P2=0X00;
P1=wei_num[1];
P2=duan_num[shi];
delay(200);
//百位显示
P2=0X00;
P1=wei_num[0];
P2=duan_num[bai];
delay(200);
}
unsigned char ADC_read()
{
unsigned char i=0,tmp=0;
SDA=1;
CS=0;
delay(2);
SCL=0;
delay(2);
SCL=1;
delay(2);
SCL=0;
delay(2);
SCL=1;
delay(2);
SCL=0;
delay(2);
for(i=0;i<8;i++)
{
tmp<<=1;
if(SDA)
tmp++;
SCL=1;
delay(2);
SCL=0;
delay(2);
}
CS=1;
return tmp;
}
**********************************************************
下午看了一部分郭天祥的第七讲,讲的是串口的内容。看讲座里说,串口这部分内容,需要掌握的主要有二:一是掌握波特率的计算方法,二是学会SCON的设置。
第七讲今天只看了大约1/3,今天很多时间都用来关注奥运了,呵呵。中国队今天得到了4枚金牌2枚银牌,成绩还是很不错的,希望以后的比赛也能够再接再厉。
晚上中国男足发挥很稳定,不该赢的比赛坚决不赢,体现了良好的心理素质。0:2负于比利时的同时,还夺取了2张红牌。
男篮的比赛开始了,对美国虽然会输,但至少还是有看头的,比男足好的多了。
明天要出去问一下回去的火车票的问题,再买根串口线带回学校用。明天的学习任务是看完郭天祥单片机讲座第7讲。
**********************************************************
题6-1:
//利用ADC0831,调动电位器,使得数码管的显示数字变化
#include
sbit SCL=P1^3; //接ADC0831的SCL端
sbit SDA=P1^4; //接ADC0831的SDA端
sbit rst=P1^5; //接DS1302的CS端
sbit CS=P1^6; //接ADC0831的CS端
unsigned char num;
unsigned char code duan_num[]={ //段选0-9编码
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char code wei_num[]={0x05,0x06,0x07}; //位选编码,顺序由高位到低位
void delay(unsigned char);
void display(unsigned char,unsigned char,unsigned char);
unsigned char ADC_read();
void main()
{
unsigned char b=254;
rst=0; //屏蔽掉DS1302芯片,防止对本实验产生冲突
while(1)
{
b++;
if(b==255)
num=ADC_read();
display(num/100,num%100/10,num%10);
}
}
void delay(unsigned char a)
{
while(a--);
}
void display(unsigned char bai,unsigned char shi,unsigned char ge)
{
//个位显示
P2=0X00;
P1=wei_num[2];
P2=duan_num[ge];
delay(200);
//十位显示
P2=0X00;
P1=wei_num[1];
P2=duan_num[shi];
delay(200);
//百位显示
P2=0X00;
P1=wei_num[0];
P2=duan_num[bai];
delay(200);
}
unsigned char ADC_read()
{
unsigned char i=0,tmp=0;
SDA=1;
CS=0;
delay(2);
SCL=0;
delay(2);
SCL=1;
delay(2);
SCL=0;
delay(2);
SCL=1;
delay(2);
SCL=0;
delay(2);
for(i=0;i<8;i++)
{
tmp<<=1;
if(SDA)
tmp++;
SCL=1;
delay(2);
SCL=0;
delay(2);
}
CS=1;
return tmp;
}
**********************************************************
下午看了一部分郭天祥的第七讲,讲的是串口的内容。看讲座里说,串口这部分内容,需要掌握的主要有二:一是掌握波特率的计算方法,二是学会SCON的设置。
第七讲今天只看了大约1/3,今天很多时间都用来关注奥运了,呵呵。中国队今天得到了4枚金牌2枚银牌,成绩还是很不错的,希望以后的比赛也能够再接再厉。
晚上中国男足发挥很稳定,不该赢的比赛坚决不赢,体现了良好的心理素质。0:2负于比利时的同时,还夺取了2张红牌。
男篮的比赛开始了,对美国虽然会输,但至少还是有看头的,比男足好的多了。
明天要出去问一下回去的火车票的问题,再买根串口线带回学校用。明天的学习任务是看完郭天祥单片机讲座第7讲。
【08.8.11】开发板上位机软件失灵?
今天看完了郭天祥单片机教程第七讲。串行口工作之前,应对其进行初始化,主要是设置产生波特率的定时器1、串行口控制和中断控制。具体步骤如下:
1、确定T1的工作方式(编程TMOD寄存器)
2、计算T1的初值(装载TH1,TL1)
3、启动T1(编程TCON中的TR1位)
4、确定串行口控制(编程SCON寄存器)
5、串行口在中断方式工作时,要进行中断设置(编程IE、IP寄存器)
接收数据分查询法和中断法。
SMOD不可位寻址,要设置SMOD,需整体设置PCON
对SMOD置位:PCON|=0X80;
对SMOD清零:PCON&=~0X80;
今天试了一下开发板自带的串口上位机软件,但却提示无法连接。目前还没有找到原因是怎么回事,或许是电脑的串口有问题?还是开发板的串口有问题,或者是需要进行一些开发板的设置?
今天中国队得到了3金,还有银牌和铜牌。
明天的任务是看郭天祥单片机第八讲。
1、确定T1的工作方式(编程TMOD寄存器)
2、计算T1的初值(装载TH1,TL1)
3、启动T1(编程TCON中的TR1位)
4、确定串行口控制(编程SCON寄存器)
5、串行口在中断方式工作时,要进行中断设置(编程IE、IP寄存器)
接收数据分查询法和中断法。
SMOD不可位寻址,要设置SMOD,需整体设置PCON
对SMOD置位:PCON|=0X80;
对SMOD清零:PCON&=~0X80;
今天试了一下开发板自带的串口上位机软件,但却提示无法连接。目前还没有找到原因是怎么回事,或许是电脑的串口有问题?还是开发板的串口有问题,或者是需要进行一些开发板的设置?
今天中国队得到了3金,还有银牌和铜牌。
明天的任务是看郭天祥单片机第八讲。
【08.8.12】初识I2C总线
今天试着写了一个串口的程序,经过几次调试,终于在实验板上通过了。一开始总是出现莫名其妙的问题,数据可以发送,但经常发送部分特定数据时,数码管显示的接收数据与发送的数据不一致。后来上网查了下,我的实验板12M晶振当在9600波特率下工作时可能会出现错误,降低波特率后程序工作正常。程序如下:
**********************************************************
题7-1:
//单片机接收串口调试器发送的数据后,先把它显示在数码管上,再把它发送回串口调试器
#include
unsigned char num,r_flag; //其中r_flag=1时表示单片机收到上位机数据
unsigned char code duanxuan[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
unsigned char code weixuan[]={0x00,0x01,0x02}; //位选编码
void delay(unsigned char);
void display(unsigned char,unsigned char,unsigned char);
void main()
{
TMOD=0X20;
TH1=0XF3; //由于是12M的晶振,因此要选2400波特率,实验中选择9600时出现传输错误
TL1=0XF3;
SM0=0;
SM1=1;
REN=1;
EA=1;
ES=1;
TR1=1;
while(1)
{
if(r_flag==1) //当接收到数据后,把数据发回到上位机
{
ES=0; //先关掉串口中断ES,防止发送数据时也进入中断程序
SBUF=num; //把num的值通过串口发送出去
while(!TI); //耐心等数据发送完毕,再把TI清零
TI=0;
r_flag=0; //把r_flag标志位清零
ES=1; //把ES再次打开,接收新的串口中断
}
display(num/100,num%100/10,num%10); //未收到数据时,程序停在此处待命
}
}
void delay(unsigned char a)
{
while(a--);
}
void display(unsigned char bai,unsigned char shi,unsigned char ge)
{
//百位显示
P2=0X00;
P1=weixuan[0];
P2=duanxuan[bai];
delay(20);
//十位显示
P2=0X00;
P1=weixuan[1];
P2=duanxuan[shi];
delay(20);
//个位显示
P2=0X00;
P1=weixuan[2];
P2=duanxuan[ge];
delay(20);
}
void chuankou() interrupt 4
{
num=SBUF; //收到数据后,将SBUF中的值读出来
RI=0; //接收数据后,需软件将RI清零
r_flag=1; //声明单片机已经接收到了数据
}
**********************************************************
今天看了一小部分第八讲的视频,讲了一些I2C总线的基础知识。因为此前只是听说过I2C,没有学过,因此还是有点生疏的。在网上下载了一份I2C总线的协议手册,以后用到的时候可以看一下。
今天中国奥运代表团得到了4枚金牌,其中男子击剑的一枚属于意外之喜。男篮的表现也很不错,居然把世界冠军西班牙队逼到了加时赛,是我赛前绝对没能想到的。女足2-0战胜了阿根廷,小组第一出线,半决赛将于8.15日对阵日本。
希望明天中国奥运代表团的表现依旧出色。
**********************************************************
题7-1:
//单片机接收串口调试器发送的数据后,先把它显示在数码管上,再把它发送回串口调试器
#include
unsigned char num,r_flag; //其中r_flag=1时表示单片机收到上位机数据
unsigned char code duanxuan[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
unsigned char code weixuan[]={0x00,0x01,0x02}; //位选编码
void delay(unsigned char);
void display(unsigned char,unsigned char,unsigned char);
void main()
{
TMOD=0X20;
TH1=0XF3; //由于是12M的晶振,因此要选2400波特率,实验中选择9600时出现传输错误
TL1=0XF3;
SM0=0;
SM1=1;
REN=1;
EA=1;
ES=1;
TR1=1;
while(1)
{
if(r_flag==1) //当接收到数据后,把数据发回到上位机
{
ES=0; //先关掉串口中断ES,防止发送数据时也进入中断程序
SBUF=num; //把num的值通过串口发送出去
while(!TI); //耐心等数据发送完毕,再把TI清零
TI=0;
r_flag=0; //把r_flag标志位清零
ES=1; //把ES再次打开,接收新的串口中断
}
display(num/100,num%100/10,num%10); //未收到数据时,程序停在此处待命
}
}
void delay(unsigned char a)
{
while(a--);
}
void display(unsigned char bai,unsigned char shi,unsigned char ge)
{
//百位显示
P2=0X00;
P1=weixuan[0];
P2=duanxuan[bai];
delay(20);
//十位显示
P2=0X00;
P1=weixuan[1];
P2=duanxuan[shi];
delay(20);
//个位显示
P2=0X00;
P1=weixuan[2];
P2=duanxuan[ge];
delay(20);
}
void chuankou() interrupt 4
{
num=SBUF; //收到数据后,将SBUF中的值读出来
RI=0; //接收数据后,需软件将RI清零
r_flag=1; //声明单片机已经接收到了数据
}
**********************************************************
今天看了一小部分第八讲的视频,讲了一些I2C总线的基础知识。因为此前只是听说过I2C,没有学过,因此还是有点生疏的。在网上下载了一份I2C总线的协议手册,以后用到的时候可以看一下。
今天中国奥运代表团得到了4枚金牌,其中男子击剑的一枚属于意外之喜。男篮的表现也很不错,居然把世界冠军西班牙队逼到了加时赛,是我赛前绝对没能想到的。女足2-0战胜了阿根廷,小组第一出线,半决赛将于8.15日对阵日本。
希望明天中国奥运代表团的表现依旧出色。
【08.8.13】I2C总线,初学不容易
今天看完了郭天祥单片机的第八讲,从8.2开始,这一讲是听的最云里雾里的。主要是对i2c事先不了解,因此讲座里讲解程序的时候也听得莫名其妙,不知道某一句到底是干什么的,起什么作用。
记得在学校图书馆看到过一本关于单片机外围电路的书,开学之后应该借来看看。像ADC0831、AT24C02这样的芯片,不熟悉的话,就根本谈不上对它们编程,而且这些都还是实际电路板上常用的。
明天计划看一看i2c的协议,再争取写一个通过i2c读写AT24C02的程序出来。
截止到今天,中国在2008年北京奥运会上已经得到了17枚金牌。
记得在学校图书馆看到过一本关于单片机外围电路的书,开学之后应该借来看看。像ADC0831、AT24C02这样的芯片,不熟悉的话,就根本谈不上对它们编程,而且这些都还是实际电路板上常用的。
明天计划看一看i2c的协议,再争取写一个通过i2c读写AT24C02的程序出来。
截止到今天,中国在2008年北京奥运会上已经得到了17枚金牌。
【08.8.14】关注奥运多于mcu
今天看了一点关于i2c的东西,没有编程。主要都看奥运会了,呵呵,跌宕起伏的赛事使得我今天也无心学习了。网易奥运频道一直F5刷新中,今天男篮战胜了安哥拉,男排也胜了日本。射箭取得了一枚突破性的金牌,这是今天含金量很重的,也是一枚意料之外的金牌。
截止到今天,中国队已经得到了22枚金牌(美国10金第二,韩国6金第三)。本届奥运会总共302枚金牌也已经决出了80多块。
截止到今天,中国队已经得到了22枚金牌(美国10金第二,韩国6金第三)。本届奥运会总共302枚金牌也已经决出了80多块。
【08.8.15】在看奥运,没学习
今天基本上没有学习,有中国队参加的精彩比赛很多,一直都在关注中。
晚上不开电脑了,从现在要一直看到晚上11点多,呵呵。
晚上不开电脑了,从现在要一直看到晚上11点多,呵呵。
【08.8.30】写I2C程序与LCD1602程序
昨天和今天加起来,把郭天祥单片机的第八讲(即I2C总线和AT24C02部分)又大体看了一遍,勉强写出了一个程序,如下:
**********************************************************
题8-1:
//将一个字节写入AT24C02中,然后再把它读出来,显示在数码管上
#include
#include
sbit scl=P3^7;
sbit sda=P3^6;
unsigned char b;
unsigned char code table[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7f,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void delay();
void long_delay();
void i2cstart();
void i2cstop();
void response();
void init();
void write_byte(unsigned char);
unsigned char read_byte();
void display(unsigned char);
void main()
{
init(); //初始化
/**********************以下为写入数据**********************/
i2cstart(); //起始信号
write_byte(0xa0); //寻找器件地址,下一个数据为单片机向存储器写入
response(); //等待回应
write_byte(3); //寻址存储器内地址“3”
response(); //等待回应
write_byte(0x05); //将数据“5”写入存储器地址“3”内
response(); //等待回应
i2cstop();
/**********************以上为写入数据**********************/
long_delay(); //读写之间停顿一下,防止器件反应不过来
/**********************以下为读取数据**********************/
i2cstart(); //起始信号
write_byte(0xa0); //寻找器件地址,伪写
response(); //等待回应
write_byte(3); //寻址存储器内地址
response(); //等待回应
i2cstart(); //起始信号
write_byte(0xa1); //寻找器件地址,读取
response(); //等待回应
b=read_byte();
response(); //等待回应
/**********************以上为读取数据**********************/
i2cstop();
display(b); //将读取到的数据显示在数码管上
}
/**********************以下为子函数定义**********************/
void delay()
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void long_delay()
{
int a=10000;
while(a--);
}
void i2cstart() //I2C起始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void i2cstop() //I2C终止信号
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void response() //应答信号
{
unsigned char i;
scl=1; //拉高时钟信号
delay();
while((sda==1)&&(i<250))i++; //sda为1说明尚未有应答产生
scl=0; //拉低时钟信号
delay();
}
void init() //上电初始化
{
scl=1;
sda=1; //释放数据线
}
void write_byte(unsigned char num1)
{
unsigned char i,temp;
temp=num1;
scl=0; //要写数据了,需将scl先拉低
delay();
for(i=0;i<8;i++)
{
temp=temp<<1;
sda=CY; //8位数据依次通过sda写入
delay();
scl=1;
delay();
scl=0;
delay();
}
sda=1; //养成良好习惯,写完数据后释放总线
delay();
}
unsigned char read_byte()
{
unsigned char i,j,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
j=sda;
k=(k<<1)|j;
scl=0;
delay();
}
sda=1;
delay();
return k;
}
void display(unsigned char num2)
{
P2=table[num2];
}
**********************************************************
下午又看了郭天祥单片机第九讲,这是第一次接触液晶显示器。讲座里讲的是1602,只能显示英文、数字及其他一些简单符号,不能显示汉字,但至少这是基础,学会了它,再接触复杂的显示器也就有了底子。
看完视频后,写了一个简单的程序,如下:
**********************************************************
题9-1:
//在液晶屏1602第一行显示“Long live”,第二行显示“China”
#include
sbit rs=P1^0; //数据/命令选择,数据为1,命令为0
sbit rw=P1^1; //读写选择端,读为1,写为0
sbit en=P1^2; //使能端
unsigned char table1[]="Long live";
unsigned char table2[]="China";
void delay(unsigned int);
void write_comm(unsigned char);
void write_data(unsigned char);
void init();
void main()
{
unsigned char i;
init();
/**************写第一行**************/
write_comm(0x80);
delay(200);
for(i=0;i<9;i++)
{
write_data(table1[i]);
delay(200);
}
/**************写第一行**************/
delay(500);
/**************写第二行**************/
write_comm(0xc0);
delay(200);
for(i=0;i<5;i++)
{
write_data(table2[i]);
delay(200);
}
/**************写第二行**************/
}
void delay(unsigned int temp)
{
while(temp--);
}
void write_comm(unsigned char comm)
{
rs=0; //命令
rw=0; //写
P2=comm;
en=0;
delay(100);
en=1; //给一个高脉冲,把数据送过去
delay(100);
en=0;
delay(100);
}
void write_data(unsigned char dat)
{
rs=1; //数据
rw=0; //写
P2=dat;
en=0;
delay(100);
en=1; //给一个高脉冲,把数据送过去
delay(100);
en=0;
delay(100);
}
void init() //LCD1602初始化
{
write_comm(0x38); //显示模式设置
delay(200);
write_comm(0x0c); //本行与下行显示开关及光标设置,含义详见1602说明
delay(200);
write_comm(0x06);
delay(200);
}
**********************************************************
至此郭天祥单片机讲座的各个分项部分就都看完了,还有三个综合课程:第十讲(利用定时器设计一个电子钟),第十一讲(利用时钟芯片设计一个电子钟),第十二讲(Protel,可能不打算看了)第十三讲(AD6.5绘图),计划回学校再看。明天还有一天的时间,收拾一下需要带的东西。
**********************************************************
题8-1:
//将一个字节写入AT24C02中,然后再把它读出来,显示在数码管上
#include
#include
sbit scl=P3^7;
sbit sda=P3^6;
unsigned char b;
unsigned char code table[]={
0x3F,0x06,0x5B,0x4F,
0x66,0x6D,0x7D,0x07,
0x7f,0x6F,0x77,0x7C,
0x58,0x5E,0x79,0x71}; //从0-F的数码管共阴极编码
void delay();
void long_delay();
void i2cstart();
void i2cstop();
void response();
void init();
void write_byte(unsigned char);
unsigned char read_byte();
void display(unsigned char);
void main()
{
init(); //初始化
/**********************以下为写入数据**********************/
i2cstart(); //起始信号
write_byte(0xa0); //寻找器件地址,下一个数据为单片机向存储器写入
response(); //等待回应
write_byte(3); //寻址存储器内地址“3”
response(); //等待回应
write_byte(0x05); //将数据“5”写入存储器地址“3”内
response(); //等待回应
i2cstop();
/**********************以上为写入数据**********************/
long_delay(); //读写之间停顿一下,防止器件反应不过来
/**********************以下为读取数据**********************/
i2cstart(); //起始信号
write_byte(0xa0); //寻找器件地址,伪写
response(); //等待回应
write_byte(3); //寻址存储器内地址
response(); //等待回应
i2cstart(); //起始信号
write_byte(0xa1); //寻找器件地址,读取
response(); //等待回应
b=read_byte();
response(); //等待回应
/**********************以上为读取数据**********************/
i2cstop();
display(b); //将读取到的数据显示在数码管上
}
/**********************以下为子函数定义**********************/
void delay()
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void long_delay()
{
int a=10000;
while(a--);
}
void i2cstart() //I2C起始信号
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void i2cstop() //I2C终止信号
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void response() //应答信号
{
unsigned char i;
scl=1; //拉高时钟信号
delay();
while((sda==1)&&(i<250))i++; //sda为1说明尚未有应答产生
scl=0; //拉低时钟信号
delay();
}
void init() //上电初始化
{
scl=1;
sda=1; //释放数据线
}
void write_byte(unsigned char num1)
{
unsigned char i,temp;
temp=num1;
scl=0; //要写数据了,需将scl先拉低
delay();
for(i=0;i<8;i++)
{
temp=temp<<1;
sda=CY; //8位数据依次通过sda写入
delay();
scl=1;
delay();
scl=0;
delay();
}
sda=1; //养成良好习惯,写完数据后释放总线
delay();
}
unsigned char read_byte()
{
unsigned char i,j,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
j=sda;
k=(k<<1)|j;
scl=0;
delay();
}
sda=1;
delay();
return k;
}
void display(unsigned char num2)
{
P2=table[num2];
}
**********************************************************
下午又看了郭天祥单片机第九讲,这是第一次接触液晶显示器。讲座里讲的是1602,只能显示英文、数字及其他一些简单符号,不能显示汉字,但至少这是基础,学会了它,再接触复杂的显示器也就有了底子。
看完视频后,写了一个简单的程序,如下:
**********************************************************
题9-1:
//在液晶屏1602第一行显示“Long live”,第二行显示“China”
#include
sbit rs=P1^0; //数据/命令选择,数据为1,命令为0
sbit rw=P1^1; //读写选择端,读为1,写为0
sbit en=P1^2; //使能端
unsigned char table1[]="Long live";
unsigned char table2[]="China";
void delay(unsigned int);
void write_comm(unsigned char);
void write_data(unsigned char);
void init();
void main()
{
unsigned char i;
init();
/**************写第一行**************/
write_comm(0x80);
delay(200);
for(i=0;i<9;i++)
{
write_data(table1[i]);
delay(200);
}
/**************写第一行**************/
delay(500);
/**************写第二行**************/
write_comm(0xc0);
delay(200);
for(i=0;i<5;i++)
{
write_data(table2[i]);
delay(200);
}
/**************写第二行**************/
}
void delay(unsigned int temp)
{
while(temp--);
}
void write_comm(unsigned char comm)
{
rs=0; //命令
rw=0; //写
P2=comm;
en=0;
delay(100);
en=1; //给一个高脉冲,把数据送过去
delay(100);
en=0;
delay(100);
}
void write_data(unsigned char dat)
{
rs=1; //数据
rw=0; //写
P2=dat;
en=0;
delay(100);
en=1; //给一个高脉冲,把数据送过去
delay(100);
en=0;
delay(100);
}
void init() //LCD1602初始化
{
write_comm(0x38); //显示模式设置
delay(200);
write_comm(0x0c); //本行与下行显示开关及光标设置,含义详见1602说明
delay(200);
write_comm(0x06);
delay(200);
}
**********************************************************
至此郭天祥单片机讲座的各个分项部分就都看完了,还有三个综合课程:第十讲(利用定时器设计一个电子钟),第十一讲(利用时钟芯片设计一个电子钟),第十二讲(Protel,可能不打算看了)第十三讲(AD6.5绘图),计划回学校再看。明天还有一天的时间,收拾一下需要带的东西。