• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

从零开始,记录每天学单片机,菜鸟一枚,勿喷!

首先,在论坛上发这帖子只是单纯的为了学习,没别意思,一来起到监督自己的作用,二来也希望广大大神可以指导指导!首先发个自己用万用板焊的简易开发板。使用STC89C52单片机。以后涉及到其他电子元件再补上去!

全部回复(16)
正序查看
倒序查看
2014-07-18 11:05
就爱看这种学习记录帖,可以陪着大家一起成长!加油哦。每天我都会来关注的。
0
回复
李丶四
LV.2
3
2014-07-21 09:34
周末回家了,家里没电脑!...今天正式开始!
0
回复
李丶四
LV.2
4
2014-07-21 10:07
公司电脑没法使用protel   等晚上回宿舍再补上原理图。
0
回复
李丶四
LV.2
5
2014-07-21 10:14
简单说一下:首先8个LED灯的负极是通过HC245连到单片机的P0口,245的作用是防止电流过大烧毁单片机,恩,我的理解是这样的;然后LED灯的正极是由三极管9012加上38译码器的Y6脚控制,38译码器的作用是节省单片机的IO口,38译码器的A0,A1,A2分别接到单片机的P1^0,P1^1,P1^2,使能端E3接P1^3,E1,E2接P1^4。
0
回复
李丶四
LV.2
6
2014-07-21 10:16
好吧  没有原理图果然很难说清楚,硬件方面的搭建因为比较简单,没太大问题,接下来我要说编程。使用当然是Keil。
0
回复
2014-07-21 10:19
@李丶四
简单说一下:首先8个LED灯的负极是通过HC245连到单片机的P0口,245的作用是防止电流过大烧毁单片机,恩,我的理解是这样的;然后LED灯的正极是由三极管9012加上38译码器的Y6脚控制,38译码器的作用是节省单片机的IO口,38译码器的A0,A1,A2分别接到单片机的P1^0,P1^1,P1^2,使能端E3接P1^3,E1,E2接P1^4。
楼主不错,记录下的成长 以后看起来也有意义呢 加油哈~~~
0
回复
李丶四
LV.2
8
2014-07-21 10:25

最简单,点亮第一个LED,绿灯。P0^0置0即可。看程序:

#include

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

sbit LED_on=P0^0;

 

void main()

{

    ADDR0=0;

    ADDR1=1;

    ADDR2=1;//因为LED正极是利用三极管9012和138的Y6口,所以Y6口必须为0,所以A0,A1,A2分别为0.1.1

    ADDR3=1;

    ADDR4=0;//138使能端,E1,E2低电平有效,E3高电平有效。    

    while(1)

    {

        LED_on=0;

    }

}

0
回复
李丶四
LV.2
9
2014-07-21 19:41
附上原理图。同样的,以后学新元件再加上去!

0
回复
李丶四
LV.2
10
2014-07-21 20:23

LED点亮后,接下来就使它有间隔的亮,需要加个延时,单片机可以利用的延时有两种!一种可以在程序上设计,利用循环函数,当到一定时间后跳出来,但不精确。另外一种可以利用单片机的定时器中断,到我们需要的时间后就中断。嗯,这里我先利用简单的,就是第一种。程序:

#include

#define uchar unsigned char

#define uint  unsigned int

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

sbit LED_on=P0^0;

void delay(uint x)     //延时子程序。

{

    uchar i; 

    while(x--) 

     {  

         for(i=0;i<120;i++);

    }

void main()

{   

     ADDR0=0;    

    ADDR1=1;    

    ADDR2=1;    //因为LED正极是利用三极管9012和138的Y6口,所以Y6口必须为0,所以A0,A1,A2分别为0.1.1    

    ADDR3=1;    

    ADDR4=0;//138使能端,E1,E2低电平有效,E3高电平有效。       

     while(1)    

    {        

        LED_on=0;

        delay(100);

        LED_on=1;

        delay(100);   

     }

}

0
回复
李丶四
LV.2
11
2014-07-21 20:26

记录学习,当然有自己错误的时候,我也把它列出来,一开始我程序的出现个错误,是error C267: 'delay': requires ANSI-style prototype

不懂自然区百度,发现别人说都是把延迟放到最前面,我试了一下,确实可以。但我觉得主程序是不是应该放最前面才合适呢,这样看起来像一个目录。希望大神能告知。

0
回复
李丶四
LV.2
12
2014-07-21 20:45

先放一边,接下来就是简单的走马灯程序:

#include

#define uchar unsigned char

#define uint  unsigned int

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

void delay(uint x)     //延时子程序。

{

    uchar i; 

    while(x--) 

     {  

         for(i=0;i<120;i++);

    }  

void main()

{   

    uchar cnt=0;    //LED指针 

    ADDR0=0;    

    ADDR1=1;    

    ADDR2=1;    //因为LED正极是利用三极管9012和138的Y6口,所以Y6口必须为0,所以A0,A1,A2分别为0.1.1    

    ADDR3=1;    

    ADDR4=0;    //138使能端,E1,E2低电平有效,E3高电平有效。       

     while(1)    

    {       

         P0=~(0x01<

        delay(100); 

        cnt++;

        if(cnt>=8)

        {

            cnt=0;

        }  

     }

}

0
回复
李丶四
LV.2
13
2014-07-21 20:52
个人感觉实现LED的这些功能,就是为了理解单片机的IO口,当然,我学的还是很皮毛,P0口是没有内置上拉电阻的,所以电路设计上需要另外加!嗯,接下来去了解定时器,单片机有两个定时器,要使它们工作,我们要在程序上编写一些条件,比如要使用定时器0,我们要这样写:TR0=1,这样定时器0就会工作,但它有很多种工作方式,准确说是4种,但我们一般都需要第一种,于是我们这样写:TMOD=0x01; 这样定时器就会以第一种方式进行定时,说来惭愧,学到这里我才理解位寻址是怎么用的,因为我发现为什么要TR0=1,然后又有TMOD=0x01这样来设置定时器呢,哦,原来一个可以位寻址,一个不可以,嗯,又学到点东西!
0
回复
李丶四
LV.2
14
2014-07-22 19:40

现在利用定时器0进行定时,就是LED之间隔一秒亮,我使用的是12M的晶振,一个时钟周期就是1/12*106,一个机械周期是12个时钟周期,1ms等于x个机械周期,算出x等于1000,65536减去1000再用16进制表示得FC18,所以我们的定时器初定值为 TH0=0xFC,TL0=0x18.程序如下:

#include

#define uchar unsigned char

#define uint  unsigned int

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

 

void main()

{

    uchar cnt=0;    //LED指针

    uint T=0;    //定时器溢出次数

    ADDR0=0;

    ADDR1=1;

    ADDR2=1;    //因为LED正极是利用三极管9012和138的Y6口,所以Y6口必须为0,所以A0,A1,A2分别为0.1.1

    ADDR3=1;

    ADDR4=0;    //138使能端,E1,E2低电平有效,E3高电平有效。

    TMOD=0x01;    //定时器选择工作模式1

    TH0=0xFC;

    TL0=0x18;    //赋予初值

    TR0=1;        //开定时器0

    while(1)

    {

    if(TF0==1)

    {

        TF0=0;

        T++;  

        TH0=0xFC;

        TL0=0x18;    //重新赋值 

    }

    if(T>=1000)

    {

        T=0;

         P0=~(0x01<

        cnt++;

        if(cnt>=8)

        {

            cnt=0;

        }

    }

    }

}

0
回复
李丶四
LV.2
15
2014-07-23 19:45

LED可以衍生到数码管,我暂时使用的是4个共阴的数码管,分别接到38译码器的Y0,Y1,Y2,Y3口,首先令一个数码管静态显示,我们在数码管看到的1,2,3,4.....9,0,是利用数码管的相对应LED组合而成,因为是共阴,所以当我们P0口给“1”的时候,LED亮。看以下程序,我想实现的功能是秒数计数:

#include

#define uchar unsigned char

#define uint  unsigned int

uchar LedChar[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//数码管输出0,1,2,3,4,5,6,7,8,9

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

 

void main()

{

    uchar cnt=0;    //秒数指针

    uint T=0;    //定时器溢出次数

    P0=0x00;    //初始化不显示

    ADDR0=1;

    ADDR1=1;

    ADDR2=0;    //因为数码管阴极是138的Y4口,所以Y3口必须为0,所以A0,A1,A2分别为1.1.0

    ADDR3=1;

    ADDR4=0;    //138使能端,E1,E2低电平有效,E3高电平有效。

    TMOD=0x01;    //定时器选择工作模式1

    TH0=0xFC;

    TL0=0x18;    //赋予初值

    TR0=1;        //开定时器0

    while(1)

    {

    if(TF0==1)

    {

        TF0=0;

        T++;  

        TH0=0xFC;

        TL0=0x18;    //重新赋值 

    }

    if(T>=1000)

    {

        T=0;

         P0=LedChar[cnt];

        cnt++;

        if(cnt>=10)

        {

            cnt=0;

        }

    }

    }

}

0
回复
李丶四
LV.2
16
2014-07-23 20:40

有静态显示,自然有动态显示,因为单片执行指令的时候是一条一条的执行,那我们是是如何实现4个数码管同时显示呢,其实是利用人的错觉,但闪烁间隔为10mS时,我们是不会感觉闪烁的,根据这个原理,我们让4个数码管同时显示:

#include

#define uchar unsigned char

#define uint  unsigned int

uchar LedChar[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//数码管输出0,1,2,3,4,5,6,7,8,9

uchar Ledsta[]={0x00,0x00,0x00,0x00};

sbit ADDR0=P1^0;

sbit ADDR1=P1^1;

sbit ADDR2=P1^2;

sbit ADDR3=P1^3;

sbit ADDR4=P1^4;

 uint T=0;

void main()

{

    uint cnt=0;    //秒数指针

    uint T=0;    //定时器溢出次数

    P0=0x00;    //初始化不显示

    EA=1;        //中断总开关

    ADDR3=1;

    ADDR4=0;    //138使能端,E1,E2低电平有效,E3高电平有效。

    TMOD=0x01;    //定时器选择工作模式1

    TH0=0xFC;

    TL0=0x18;    //赋予初值

    TR0=1;        //开定时器0

    ET0=1;        //定时器中断0开关

    while(1)

    {

        if(T>=1000)

        {

            cnt++;

            Ledsta[0]=LedChar[cnt%10];

            Ledsta[1]=LedChar[cnt/10%10];

            Ledsta[2]=LedChar[cnt/100%10];

            Ledsta[3]=LedChar[cnt/1000%10];

        }

    }

}

void InterruptTimer0() interrupt 1

{

    static uchar i=0;

    T++;  

    TH0=0xFC;

    TL0=0x18;

    switch(i)

    {

        case 0: ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=Ledsta[0];break;

        case1:  ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=Ledsta[1];break;

        case2:  ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=Ledsta[2];break;

        case3:  ADDR0=0;ADDR1=0;ADDR2=0;i=0;P0=Ledsta[3];break;

        default:break;

    }

}

0
回复
2014-08-19 10:05
@李丶四
有静态显示,自然有动态显示,因为单片执行指令的时候是一条一条的执行,那我们是是如何实现4个数码管同时显示呢,其实是利用人的错觉,但闪烁间隔为10mS时,我们是不会感觉闪烁的,根据这个原理,我们让4个数码管同时显示:#include#defineucharunsignedchar#defineuint unsignedintucharLedChar[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//数码管输出0,1,2,3,4,5,6,7,8,9ucharLedsta[]={0x00,0x00,0x00,0x00};sbitADDR0=P1^0;sbitADDR1=P1^1;sbitADDR2=P1^2;sbitADDR3=P1^3;sbitADDR4=P1^4; uintT=0;voidmain(){  uintcnt=0;  //秒数指针  uintT=0;  //定时器溢出次数    P0=0x00;  //初始化不显示  EA=1;      //中断总开关    ADDR3=1;    ADDR4=0;    //138使能端,E1,E2低电平有效,E3高电平有效。  TMOD=0x01;  //定时器选择工作模式1  TH0=0xFC;  TL0=0x18;  //赋予初值  TR0=1;      //开定时器0  ET0=1;      //定时器中断0开关    while(1)    {      if(T>=1000)      {          cnt++;          Ledsta[0]=LedChar[cnt%10];          Ledsta[1]=LedChar[cnt/10%10];          Ledsta[2]=LedChar[cnt/100%10];          Ledsta[3]=LedChar[cnt/1000%10];      }  }}voidInterruptTimer0()interrupt1{  static uchari=0;  T++;      TH0=0xFC;  TL0=0x18;  switch(i)  {      case0:ADDR0=1;ADDR1=1;ADDR2=0;i++;P0=Ledsta[0];break;      case1: ADDR0=0;ADDR1=1;ADDR2=0;i++;P0=Ledsta[1];break;      case2: ADDR0=1;ADDR1=0;ADDR2=0;i++;P0=Ledsta[2];break;      case3: ADDR0=0;ADDR1=0;ADDR2=0;i=0;P0=Ledsta[3];break;      default:break;  }}
楼主还在么 继续啊
0
回复