Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6721
  • 博文数量: 1
  • 博客积分: 105
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-11 12:00
文章分类
文章存档

2012年(1)

我的朋友
最近访客

分类:

2012-10-25 00:46:15

【08.8.3】新的开始
自4.20号之后,单片机的学习基本上处于停滞状态。
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】流水灯与蜂鸣器
今天上午和中午做了第二讲剩余的三个课后作业。程序如下,已经在开发板上调试通过。
**********************************************************
题目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艰难战胜小组最强的对手瑞典队,出线形势一片大好。希望这场开门红也能预示着中国奥运代表团的好运吧。
明晚中国男足也要出场了,据说对手新西兰比较弱,国奥可能会取得历史的突破。不过中国男子足球向来都是给人以失望的多,明晚看看吧。

明天的学习计划:看郭天祥单片机第四讲。
【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届奥运会的开幕式了,期待中……

明天的学习任务是看郭天祥单片机讲座第五章。

【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中写了一个矩阵键盘的程序,但是今天尚未调试好,明天再说。
奥运会开幕式已经开始了!今天就先写到这儿吧。去看电视了~~~~

祝福中国!

【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了,明天再说吧。

【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讲。

【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金,还有银牌和铜牌。

明天的任务是看郭天祥单片机第八讲。

【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日对阵日本。

希望明天中国奥运代表团的表现依旧出色。

【08.8.13】I2C总线,初学不容易
今天看完了郭天祥单片机的第八讲,从8.2开始,这一讲是听的最云里雾里的。主要是对i2c事先不了解,因此讲座里讲解程序的时候也听得莫名其妙,不知道某一句到底是干什么的,起什么作用。

记得在学校图书馆看到过一本关于单片机外围电路的书,开学之后应该借来看看。像ADC0831、AT24C02这样的芯片,不熟悉的话,就根本谈不上对它们编程,而且这些都还是实际电路板上常用的。

明天计划看一看i2c的协议,再争取写一个通过i2c读写AT24C02的程序出来。

截止到今天,中国在2008年北京奥运会上已经得到了17枚金牌。

【08.8.14】关注奥运多于mcu
今天看了一点关于i2c的东西,没有编程。主要都看奥运会了,呵呵,跌宕起伏的赛事使得我今天也无心学习了。网易奥运频道一直F5刷新中,今天男篮战胜了安哥拉,男排也胜了日本。射箭取得了一枚突破性的金牌,这是今天含金量很重的,也是一枚意料之外的金牌。

截止到今天,中国队已经得到了22枚金牌(美国10金第二,韩国6金第三)。本届奥运会总共302枚金牌也已经决出了80多块。

【08.8.15】在看奥运,没学习
今天基本上没有学习,有中国队参加的精彩比赛很多,一直都在关注中。

晚上不开电脑了,从现在要一直看到晚上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绘图),计划回学校再看。明天还有一天的时间,收拾一下需要带的东西。
阅读(704) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~