技术中心

基本模型的建立

西安誉通光电测控有限责任公司

2010/4/21 17:10:04>> 进入商铺
导读:

 

写给我的兄弟姐妹们十
―基本模型的建立(图+程序)
上学的时候我“理科”学的很不错,其中很重要的原因之一就是我在学习的时候注重“基本模型”的建立,学习“嵌入式开发”也不例外,我们知道“单片机和外围功能器件构成基本硬件系统”+输入控制+输出控制=“目的系统”,很多书上从多个方面阐述其工作机理,要了解个中究竟就去看书吧;我在此只按照自己的理解方式给大家划分和讲解,目的是整理出思路来:不论键盘、鼠标等等输入,还是LCD、LED、CRT的显示,继电器、AD、DA等等,对于单片机来讲只是“控制方式”不同,而控制方式一般可分为---总线方式和I/O模拟方式;
那么首先要建立的模型是:
1.       单片机+键盘+LED灯;
这里的键盘是低电平有效,程序里用查询方式,当然你也可以高电平有效方式,把键盘和电阻的位置调换就可以了,同时可以用中断方式,当多个键盘共用一个中断的时候加一个74HC4078就可以了,如果牵扯到电平取反则加一个74HC04即可;这个实验是练习基本的I/O口控制;
2.       单片机+LCD;
使用总线控制和I/O控制两种方式来控制LCD;
3.       单片机+通信+LED数码等等(寄存器的设置+基本通信协议的理解+I/O模拟控制等等)具体有例子程序;
/* 实验一  LED流水灯 */
#Include <REG51.H>
void delay(void)
{ unsigned int i,j,k,l;
  for(i=0;i<=27000;i++)
  {j++; k++;l++;};
}
void main (void)
{ unsigned char i,c[4] = {0xef,0xdf,0xbf,0x7f};// 从左往右流水
 i = 0;
 while(1)
 {    P3 = c[i & 3];
      i++;
        delay();
   }
}
//=========================================================================
// 实验二  用一位数码管循环显示0~9
#Include <REG51.H>
#define U8 unsigned char
code U8 tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28};
void delay(void)
{ unsigned int i,j,k,l;
  for(i=0;i<=27000;i++)
  {j++; k++;l++;};
}
void main(void)
{ U8 i;
 P2_4=0;
 while(1)
 { P0 = tab[i];
  delay();
  i++;
  if(i==10) i = 0;
 }
}
//=============================================================================
// 实验三  LED数码管的动态驱动
#Include <REG51.H>
#define U8 unsigned char
U8 tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28};
U8 scn[]={0x7f,0xbf,0xdf,0xef};//先点亮左边一个数码管
U8 buf[4]={0,0,0,0};// 显示缓冲区,开机先显示"0000"
U8 cnt = 0;   // 扫描计数
void main(void)
{ EA = 1;   // 允许中断
 TMOD = 0x01; // 设定时器0为模式1(16位)
 ET0 = 1;   // 定时器0中断允许
 TH0 = 0xee;  // 晶振11.0592MHz,5mS
 TL0 = 0;   
 TR0 = 1;  // 开始计数
 while(1);   // 死循环,等待中断
}
void timeint(void) interrupt 1 // 定时器0中断服务程序
{ char i;
 TH0 = 0xee;      // 设置定时器时间常数
 TL0 = 0;
 i = cnt & 0x03;  // 求应点亮的LED号(从左到右依次为 0,1,2,3)
 P0 = tab[buf[i]]; // 笔划代码送P0口 
 P2 = scn[i];  // 控制扫描码送P2口
 if(cnt==200)
 { cnt=0;   // 到1秒钟,显示的数字加一
  for(i=3;i>=0;i--)
  {   buf[i]++;
      if(buf[i]==10) buf[i]=0;// 加到10向前进位
      else break;
  }
 }
 cnt++;
}
//====================================================================
// 实验四  自动演奏乐曲-康定情歌
#Include <REG51.h>
#define U8 unsigned char
code unsigned int cyc[]={1800,1600,1440,1351,1200,1079,960};//音阶1-7的半周期数
code U8 tone[]={13,15,16,16,15,16,13,12,12,13,15,16,16,15,16,13,13, 13,15,16,
16,15,16,13,12,12,15,13,12,13,12,11,12,6,6,12,15,13,12,6,6,15,13,12,13,12,11,
12,6,5,6,0xff};// 乐曲《康定情歌》的简谱表
code U8 time[]={8,8,8,4,4,8,8,12,4,8,8,8,4,4,8,16,8,8,8,8,4,4,8,8,12,4,8,8,4,4, 4,4,8,24,8,24,8,24,8,16,8,8,8,4,4,4,4,8,16,8,32};// 节拍表
U8 H0,L0,cnt;
void cntint0(void) interrupt 1 // 定时器0中断用于产生音阶方波
{ TH0=H0;
 TL0=L0;
 P2_3=~P2_3;                // P2.3是音乐信号输出脚,P2.3反相,产生方波
}
void cntint1(void) interrupt 3  // 定时器1中断用于产生节拍延时
{ cnt++;                     // 计数初值为0,所以不用赋值
}
void main(void)
{ U8 i,a,t;
unsigned int b;
next:TMOD=0x11;
 EA=1;
 ET0=1;
 ET1=1;
 cnt=0;
 TR1=1;
 i=0;
 while(1)
 { t=tone[i];           // 读音调
  if(t==0xff) break;    // 0xff是结束符
  if(t!=0)      // 0 是休止符 
  { b=cyc[t%10-1];   // 根据基本音阶,求出半周期数
   if(t<10) b=b*2;   // 若是低八度音阶,半周期数加倍
   if(t>20) b=b/2;   // 若是高八度音阶,半周期数减半
   H0=(65536-b)/256; // 根据半周期数,计算T0初值的高字节和低字节
   L0=(65536-b)%256;
   TR0=1;        // 启动定时器0发音
  }
  cnt=0;
  a=time[i];           // 读节拍
  while(a>cnt);
  TR0=0;
  i++;
  for(b=0;b<1000;b++);  // 稍加延时,增强节奏感
 }
 P2_3=1;                // 关闭喇叭
 while(P3_2==1);           // 等待按INT键
 goto next;               // 重放一遍
}
//===========================================================================
// 实验五  加法计算器
#Include <REG51.H>
#define U8 unsigned char
#define key_port P1
code U8 kcode[]={0xb7,0xbe,0xde,0xee,0xbd,0xdd,0xed,0xbb,0xdb,0xeb,0xd7,0xe7};
//反转码对应键值  0    1    2    3    4    5    6    7    8    9    A    B
code U8 disp[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff};
U8 buf[4]={0,0,0,0};
U8 cnt=0;
U8 scn[]={0x7f,0xbf,0xdf,0xef};// 先点亮左边一个数码管
void delay_ms(U8 ms)
{ U8 i,j;
 for(i=0;i<100;i++)
 { for(j=0;j<ms;j++);};
}
U8 key(void)
{ U8 a,r;
 delay_ms(20); // 延时20毫秒,消除按键抖动
 if(key_port == 0xf0) goto rn;
 a = key_port;
 key_port = a | 0x0f;
 delay_ms(20);
 a = key_port;
 for (r = 0;r <= 11;r++)
 {    if(a == kcode[r]) break;};
 if(r > 11) r = 0xff; //0xff表示无效
rn: key_port = 0xf0;
 return r;
}
void main(void)
{ U8 k,i,pf;  // pf为按过加号键的标志
 int p,p1,p2, // p1,p2为两个加数,p为和
 TMOD = 0x01;    // 设定时器0为模式1(16位)
 TH0 = 0xee;     // 晶振11.0592MHz,5mS
 TL0 = 0; 
 TR0 = 1;     // 开始计数
 EA = 1;      // 允许中断
 ET0 = 1;      // 定时器0中断允许
 key_port = 0xf0;
 pf = 0;      // 清除加号标志
 p = 0;
 delay_ms(20);
 while(1)      // 循环
 {   if (key_port != 0xf0)
     {   k = key();
         if (k < 10)
         {   if((p1==0)&&(p2==0))for(i=0;i<=3;i++) buf[i] = 0;//清空显示缓冲区
          else for(i=1;i<=3;i++) buf[i-1]=buf[i];// 数字左移一位
          buf[3] = k;// 在个位显示刚按的数字
          if(pf==0) p1 = p1 * 10 + k;
    else p2 = p2 * 10 + k;
    }
      else
      {   if(pf == 1)
          { p = p1 + p2;
           p1 = 1000;
           for(i=0;i<3;i++)
           {   buf[i] = p / p1;
            p = p - p1 * buf[i];
               p1 = p1 / 10;
           }
           buf[3] = p;
     p = 0;
     p1 = 0;
     p2 = 0;
     pf = 0;
          }
          else
          { pf = 1;
           p2 = 0;
           for(k=0;k<=3;k++) buf[k] = 0;
    }
      }
         while(key_port != 0xf0);// 等待按键抬起
         delay_ms(20);
         while(key_port != 0xf0);
     }
 }
}
void timeint(void) interrupt 1 // 定时器0中断服务程序
{ unsigned char i,s;
 TH0 = 0xee;      // 设置定时器时间常数
 TL0 = 0;
 i = cnt & 0x03;     // 求应点亮的LED号(从左到右依次为 0,1,2,3)
 P0 = disp[buf[i]];  // 笔划代码送P0口 
P2 = scn[i];  // 控制扫描码送P2口
 cnt++;
}

相关技术

您的留言已提交成功~

采购或询价产品,请直接拨打电话联系

联系人:mahuaqiang

联系方式:
当前客户在线交流已关闭
请电话联系他 :