您的位置:控制工程论坛网论坛 » 教程与手册 » 单片机学习

常青树

常青树   |   当前状态:在线

总积分:1421  2025年可用积分:0

注册时间: 2008-09-28

最后登录时间: 2012-05-30

空间 发短消息加为好友

单片机学习

常青树  发表于 2008/10/3 20:49:40      601 查看 1 回复  [上一主题]  [下一主题]

手机阅读

 

  目前,很多人对汇编语言并不认可。可以说,掌握用C语言单片机编程很重要,可以大大提高开发的效率。不过初学者可以不了解单片机的汇编语言,但一定要了解单片机具体性能和特点,不然在单片机领域是比较致命的。如果不考虑单片机硬件资源,在KEIL中用C胡乱编程,结果只能是出了问题无法解决!可以肯定的说,最好的C语言单片机工程师都是从汇编走出来的编程者因为单片机的C语言虽然是高级语言,但是它不同于台式机个人电脑上的VC++什么的单片机的硬件资源不是非常强大,不同于我们用VC、VB等高级语言在台式PC上写程序毕竟台式电脑的硬件非常强大,所以才可以不考虑硬件资源的问题。
  以8051单片机为例讲解单片机的引脚及相关功能;
  《单片机引脚图》
  40个引脚按引脚功能大致可分为4个种类:电源、时钟、控制和I/O引脚。
  ⒈ 电源:
  ⑴ VCC - 芯片电源,接+5V;
  ⑵ VSS - 接地端;
  注:用万用表测试单片机引脚电压一般为0v或者5v,这是标准的TTL电平。但有时候在单片机程序正在工作时候测试结果并不是这个值而是介于0v-5v之间,其实这是万用表的响应速度没这么快而已,在某一个瞬间单片机引脚电压仍保持在0v或者5v。
  ⒉ 时钟:XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。
  ⒊ 控制线:控制线共有4根,
  ⑴ ALE/PROG:地址锁存允许/片内EPROM编程脉冲
  ① ALE功能:用来锁存P0口送出的低8位地址
  ② PROG功能:片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉冲。
  ⑵ PSEN:外ROM读选通信号。
  ⑶ RST/VPD:复位/备用电源。
  ① RST(Reset)功能:复位信号输入端。
  ② VPD功能:在Vcc掉电情况下,接备用电源。
  ⑷ EA/Vpp:内外ROM选择/片内EPROM编程电源。
  ① EA功能:内外ROM选择端。
  ② Vpp功能:片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。
  ⒋ I/O线
  80C51共有4个8位并行I/O端口:P0、P1、P2、P3口,共32个引脚。
  P3口还具有第二功能,用于特殊信号输入输出和控制信号(属控制总线)
  单片机模拟I2C总线及24C02读写实例
  发布日期:2008-5-14 13:38:16 文章来源:非本站原创 浏览次数: 18
  * 51系列单片机在使用时,有时需要模拟I2C总线, */
  /* 这里举出一个实例(读写串行EEPROM芯片at2402) */
  /************************************************************************/
  /* Name:AT24C02存储器的读写程序,用到I2C总线,含相对独立的I2C总线读写函数 */
  /* Language: C51单片机编程语言 */
  /* Platform: Win98,Intel Celeron 433 Processor,伟福仿真器,仿真8751 */
  /* Date: 2003年5月21日,5月22日,5月29日 */
  /* Version: 1.1.1 */
  /* Others: None */
  /************************************************************************/
  #include<string.h>
  #include<reg52.h>
  #include<intrins.h>
  #define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/
  #define TRUE 1
  #define FALSE 0
  sbit SCL=P1^7;/*假设由P1.7和P1.6控制*/
  sbit SDA=P1^6;
  /********** Function Definition 函数定义 ************/
  void DELAY(unsigned int t) /*延时函数*/
  {
  while(t!=0)
  t--;
  }
  void I2C_Start(void)
  {
  /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
  SDA=1;
  SCL=1;
  DELAY(DELAY_TIME);
  SDA=0;
  DELAY(DELAY_TIME);
  SCL=0;
  DELAY(DELAY_TIME);
  }
  void I2C_Stop(void)
  {
  /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
  SDA=0;
  SCL=1;
  DELAY(DELAY_TIME);
  SDA=1;
  DELAY(DELAY_TIME);
  SCL=0;
  DELAY(DELAY_TIME);
  }
  void SEND_0(void) /* SEND ACK */
  {
  /*发送0,在SCL为高电平时使SDA信号为低*/
  SDA=0;
  SCL=1;
  DELAY(DELAY_TIME);
  SCL=0;
  DELAY(DELAY_TIME);
  }
  void SEND_1(void)
  {
  /*发送1,在SCL为高电平时使SDA信号为高*/
  SDA=1;
  SCL=1;
  DELAY(DELAY_TIME);
  SCL=0;
  DELAY(DELAY_TIME);
  }
  bit Check_Acknowledge(void)
  {
  /*发送完一个字节后检验设备的应答信号*/
  SDA=1;
  SCL=1;
  DELAY(DELAY_TIME/2);
  F0=SDA;
  DELAY(DELAY_TIME/2);
  SCL=0;
  DELAY(DELAY_TIME);
  if(F0==1)
  return FALSE;
  return TRUE;
  }
  void WriteI2CByte(char b)reentrant
  {
  /*向I2C总线写一个字节*/
  char i;
  for(i=0;i<8;i++)
  if((b<<i)&0x80)
  SEND_1();
  else
  SEND_0();
  }
  char ReadI2CByte(void)reentrant
  {
  /*从I2C总线读一个字节*/
  char b=0,i;
  for(i=0;i<8;i++)
  {
  SDA=1; /*释放总线*/
  SCL=1; /*接受数据*/
  DELAY(10);
  F0=SDA;
  DELAY(10);
  SCL=0;
  if(F0==1)
  {
  b=b<<1;
  b=b|0x01;
  }
  else
  b=b<<1;
  }
  return b;
  }
  /**********以下为读写24c02的函数**********/
  void Write_One_Byte(char addr,char thedata)
  {
  bit acktemp=1;
  /*write a byte to mem*/
  I2C_Start();
  WriteI2CByte(0xa0);
  acktemp=Check_Acknowledge();
  WriteI2CByte(addr);/*address*/
  acktemp=Check_Acknowledge();
  WriteI2CByte(thedata);/*thedata*/
  acktemp=Check_Acknowledge();
  I2C_Stop();
  }
  void Write_A_Page(char *buffer,char addr)
  {
  bit acktemp=1;
  bit wrtmp;
  int i;
  /*write a page to at24c02*/
  I2C_Start();
  WriteI2CByte(0xa0);
  acktemp=Check_Acknowledge();
  WriteI2CByte(addr);/*address*/
  acktemp=Check_Acknowledge();
  for(i=0;i<7;i++)
  {
  WriteI2CByte(buffer);
  if(!Check_Acknowledge())
  {
  I2C_Stop();
  }
  }
  I2C_Stop();
  }
  char Read_One_Byte(char addr)
  { bit acktemp=1;
  char mydata;
  /*read a byte from mem*/
  I2C_Start();
  WriteI2CByte(0xa0);
  acktemp=Check_Acknowledge();
  WriteI2CByte(addr);/*address*/
  acktemp=Check_Acknowledge();
  I2C_Start();
  WriteI2CByte(0xa1);
  acktemp=Check_Acknowledge();
  mydata=ReadI2CByte();
  acktemp=Check_Acknowledge();
  return mydata;
  I2C_Stop();
  }
  void Read_N_Bytes(char *buffer,char n,char addr)
  {
  bit acktemp=1;
  int i=0;
  /*read 8 bytes from mem*/
  I2C_Start();
  WriteI2CByte(0xa0);
  acktemp=Check_Acknowledge();
  WriteI2CByte(addr);/*address*/
  acktemp=Check_Acknowledge();
  I2C_Start();
  WriteI2CByte(0xa1);
  acktemp=Check_Acknowledge();
  for(i=0;i<n;i++)
  {
  buffer=ReadI2CByte();
  if(i!=n-1)
  SEND_0(); /*发送应答*/
  else
  SEND_1(); /*发送非应答*/
  }
  I2C_Stop();
  }
  void main()
  {
  int i;
  char mybyte;
  char myarray[8];
  char myarray2[8];
  char rdarray[16];
  for(i=0;i<8;i++)
  {
  myarray=i;
  myarray2=i+0x08;
  }
  Write_One_Byte(0x20,0x28);
  Write_A_Page(myarray,0x10);
  Write_A_Page(myarray2,0x18);
  mybyte=Read_One_Byte(0x20);
  Read_N_Bytes(rdarray,16,0x10);
  }
1楼 0 0 回复