⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 完全实用化的020 smbus程序(与时钟pcf8563通信).txt

📁 完全实用化的020 SMBUS程序(与时钟PCF8563通信
💻 TXT
字号:
完全实用化的020 SMBUS程序(与时钟PCF8563通信)

            完全实用化的020 SMBUS程序(与时钟PCF8563通信) 
                        收集:杨本荣  来源: 网络   发表于 2005-9-3 

                  //C8051F 单片机:完全实用化的020 SMBUS程序(与时钟PCF8563通信)
                  #include <intrins.h>
                  #include <stdio.h>
                  #include <absacc.h>
                  #include <C8051F020.h>
                  #define _Nop_() _nop_()
                  #define uint unsigned int
                  #define uchar unsigned char
                  #define ulong unsigned long
                  #define MY_ADD 0x00 //SMBus从地址,B0是应答呼叫地址允许位(1允许), 
                  /*---------------------------定义PCD8583有关地址-----------------------------*/
                  #define write_pcf8563 0xA2
                  #define read_pcf8563 0xA3
                  #define pcf8563_control1 0x00
                  #define pcf8563_control2 0x01
                  #define pcf8563_second 0x02
                  #define pcf8563_minute 0x03
                  #define pcf8563_hour 0x04 //B7=0/1--24/12h B6=0/1--AM/PM 
                  B5B4(ten hours 0 to 2) B3~B0(Unit hours) 
                  #define pcf8563_date 0x05 //B7B6(year 0 to 3) B5B4(ten days 0 
                  to 3) B3~B0(Unit days)
                  #define pcf8563_week 0x06 //B7_B5(Weekdays 0 to 6) B4(ten 
                  months) B3~B0(Unit months)
                  #define pcf8563_month 0x07
                  #define pcf8563_year 0x08
                  #define pcf8563_min_arm 0x09
                  #define pcf8563_hou_arm 0x0a
                  #define pcf8563_dat_arm 0x0b
                  #define pcf8563_wek_arm 0x0c
                  #define pcf8563_clk_reg 0x0d
                  #define pcf8563_arm_reg 0x0e
                  #define pcf8563_tim_arm 0x0F
                  /*---------------------------PCF8583有关的变量----------------------------*/
                  bit dis_clock_flag,read_clock_flag,set_clock_flag;
                  uchar year,year1,month,day,week,hour,minute,second;
                  /*---------------------------SMBUS接口相关变量----------------------------*/
                  bit iic_error_flag,sm_busy;
                  uchar watch_buf[20];
                  uchar iic_read_buf[20]={0};
                  uchar iic_write_buf[20]={0};
                  uchar 
                  slave_add,iic_ram_add,send_byte,write_start_num,read_start_num;
                  uchar 
                  iic_send_count,iic_receive_count,iic_send_len,iic_receive_len,watch,i;

                  uchar hex_bcd(uchar hex_value)//完成HEX(99以内)到BCD(两位)的确转换
                  {
                  return(((hex_value/10)<<4)|(hex_value%10));
                  }

                  void enable_wdog(void)
                  {
                  WDTCN=0xA5; 
                  //允许看门狗定时器工作
                  }

                  void disable_wdog(void) //禁止看门狗定时器工作
                  {
                  WDTCN=0xDE;
                  WDTCN=0xAD;
                  }

                  void init_sysclk (void)
                  {
                  uint i=0;
                  OSCXCN=0x67; // start 
                  //external oscillator with 12MHz crystal
                  for(i=0;i<256;i++); // XTLVLD blanking 
                  while(!(OSCXCN & 0x80)); // Wait for crystal osc. to settle
                  OSCICN=0x08;
                  // OSCICN=0x17; //bit7=0:禁止时钟丢失检测 bit3=1:选择外部时钟
                  }

                  void init_smbus(void)
                  {
                  SMB0CN=0x44; //IIC总线控制寄存器01000100
                  SMB0CR=0xc4; //-(SYSCLK/2*SCL_BAUD);IIC总线速率寄存器SCL=100K
                  SMB0ADR=MY_ADD; //设置从方式时将要应答的从地址 EIE1=EIE1|0x02; 
                  //允许IIC总线中断,标志位是SI(SMB0CN.3)
                  EIP1=EIP1|0x02; //SMBUS中断为高优先级
                  }

                  void init_ioport()
                  {
                  XBR0=0x07; //b2=1 TXD0-P0.0 RXD0-P0.1,b1=1 
                  SPI_SCK--P0.2,SPI_MISO--P0.3

                  //SPI_MOSI--P0.4,SPI_NSS--P0.5,b0=1 SDA--P0.6,SCL--P0.7,
                  XBR1=0x24; //b2=1 int0--P1.0,b4=1 int1--P1.1
                  XBR2=0x40; //端口I/O弱上拉允许,交叉开关允许

                  P0MDOUT=0x00; //端口0输出方式寄存器:1--推挽方式,0--漏极开路
                  P0=0xff;

                  P1MDIN=0XFF; //端口1输入方式寄存器:1--配置为模拟输入,0--配置为数字输入
                  P1MDOUT=0xff; //端口1输出方式寄存器:1--推挽方式,0--漏极开路
                  P1=0xff;

                  P2MDOUT=0x38; //端口2输出方式寄存器:1--推挽方式,0--漏极开路
                  P2=0xff; //在该程序中P2.012为键盘扫描输入,如果为推挽方式则不可靠膸

                  P3MDOUT=0X00; //端口3输出方式寄存器:1--推挽方式,0--漏极开路
                  P3=0xff;

                  P74OUT=0x01; //端口7-4输出方式寄存器:1--推挽方式,0--漏极开路
                  P4=0xff;
                  P5=0xff;
                  P6=0xff;
                  P7=0xff;
                  }

                  void smbus_send (uchar chip_select,byte_address,write_num)
                  {
                  while(sm_busy); // Wait for SMBus to be free.
                  sm_busy=1; // Occupy SMBus (set to busy)
                  write_start_num=0;
                  slave_add=chip_select; // Chip select + WRITE
                  iic_ram_add=byte_address; // PCF8563的寄存器地址
                  iic_send_len=write_num; // 写PCF8563字节数
                  STA=1; // Start transfer
                  while (sm_busy);
                  }

                  void smbus_receive (uchar chip_select,receive_num)
                  { 
                  while (sm_busy); // Wait for bus to be free.
                  sm_busy=1; // Occupy SMBus (set to busy)
                  read_start_num=0;
                  slave_add=chip_select; // Chip select + READ
                  iic_receive_len=receive_num; 
                  STA=1; // Start transfer
                  while(sm_busy); // Wait for transfer to finish
                  }

                  void write_8563(uchar ram_add,write_num)
                  {
                  smbus_send(write_pcf8563,ram_add,write_num);
                  }

                  void read_8563(uchar read_num)
                  {
                  smbus_receive(read_pcf8563,read_num);
                  }

                  void set_clock(void)
                  {
                  iic_write_buf[0]=hex_bcd(second); //设置秒
                  iic_write_buf[1]=hex_bcd(minute); //设置分
                  iic_write_buf[2]=hex_bcd(hour); //设置时
                  iic_write_buf[3]=hex_bcd(day); 
                  iic_write_buf[4]=hex_bcd(week); 
                  iic_write_buf[5]=hex_bcd(month); 
                  iic_write_buf[6]=hex_bcd(year); 
                  write_8563(pcf8563_second,0x07);
                  }

                  void read_clock(void)
                  {
                  write_8563(pcf8563_second,0x00);
                  smbus_receive(read_pcf8563,0x07);
                  second=iic_read_buf[0]&0x7f;
                  second=((second&0xf0)>>4)*10+(second&0x0f);//将BCD码转换成HEX
                  minute=iic_read_buf[1]&0x7f;
                  minute=((minute&0xf0)>>4)*10+(minute&0x0f);//将BCD码转换成HEX
                  hour=iic_read_buf[2]&0x3f;
                  hour=((hour&0xf0)>>4)*10+(hour&0x0f);//将BCD码转换成HEX
                  day=iic_read_buf[3]&0x3f;
                  day=((day&0xf0)>>4)*10+(day&0x0f);//将BCD码转换成HEX
                  week=iic_read_buf[4]&0x07;
                  week=((week&0xf0)>>4)*10+(week&0x0f);//将BCD码转换成HEX
                  month=iic_read_buf[5]&0x1f; 
                  month=((month&0xf0)>>4)*10+(month&0x0f);//将BCD码转换成HEX
                  year=iic_read_buf[6];
                  year=((year&0xf0)>>4)*10+(year&0x0f);//将BCD码转换成HEX
                  }

                  void init_pcf8563(void)
                  {
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_control1,0x01);
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_control2,0x01);
                  iic_write_buf[0]=0x80;
                  write_8563(pcf8563_clk_reg,0x01);//CLK输出频率32.768K
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_min_arm,0x01);//分报警无效
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_hou_arm,0x01);//时报警无效
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_dat_arm,0x01);//日报警无效
                  iic_write_buf[0]=0x00;
                  write_8563(pcf8563_wek_arm,0x01);//星期报警无效
                  }

                  void smbus(void) interrupt 7 using 2 //SMBUS中断服务程序
                  {
                  watch=SMB0STA;
                  switch (watch) 
                  //SMBUS状态寄存器SMB0STA
                  { 
                  //iic_error_flag=1说明SMBus有问题
                  case 0x08: 
                  //主发送/接收:起始条件已发出. 


                  STA=0;iic_error_flag=0;AA=1; //人工清除起始位STA
                  iic_receive_count=0;iic_send_count=0;
                  SMB0DAT=slave_add; 
                  //从地址+读/写标志送SMB0DAT,
                  break; 

                  case 0x10: 
                  //主发送/接收:重复起始条件已发出。
                  STA=0;AA=1; 
                  //人工清除起始位STA
                  SMB0DAT=slave_add; 
                  //从地址+读/写标志送SMB0DAT
                  iic_receive_len=iic_receive_len+iic_receive_count;
                  iic_send_len=iic_send_len+iic_send_count;
                  iic_receive_count=0;iic_send_count=0;
                  break;
                  case 0x18: //主发送器:从地址+写标志已发出,收到ACK
                  SMB0DAT=iic_ram_add;write_start_num=0;//将要发送的数据装入SMB0DAT.
                  break; 

                  case 0x20: 
                  //主发送器:从地址+写标志已发出,收到NACK
                  write_start_num++;
                  if(write_start_num>5)
                  {STO=1;sm_busy=0;iic_error_flag=1;}//如果超过5次不成功则释放总线 
                  else{STO=1;STA=1;} //确认查询重复,置位STO+STA。
                  break;
                  case 0x28: //数据字节已发出,收到ACK,将下一字节装入SMB0DAT;
                  switch(iic_send_len)
                  {
                  case 0x00: 
                  STO=1;sm_busy=0; //如果数据已经发送结束则释放总线 
                  break; 
                  default :
                  SMB0DAT=iic_write_buf[iic_send_count++];iic_send_len--; 
                  break;
                  }
                  break;
                  case 0x30: //主发送器:数据字节已发出,收到NACK,
                  write_start_num++;
                  if(write_start_num>5)
                  { STO=1;sm_busy=0;iic_error_flag=1;}//如果超过5次不成功则释放总线 
                  else
                  {STO=1;STA=1;} //重试传输或置位STO
                  break;
                  case 0x38: //主发送器:竞争失败,保存当前数据
                  write_start_num++;
                  if(write_start_num>5)
                  {STO=1;sm_busy=0;iic_error_flag=1;} //如果超过5次不成功则释放总线 
                  {STO=1;STA=1;}
                  break;
                  case 0x40: 
                  read_start_num=0; //主接收器:从地址+读标志已发出,收到ACK,
                  if(iic_receive_len<2)AA=0; //如果只接收一个字节,清AA位(收到字节后发NACK),等待接收数据
                  break;
                  case 0x48: //主接收器:从地址+读标志已发出,收到NACK,
                  read_start_num++;
                  if(read_start_num>5)
                  {STO=1;sm_busy=0;iic_error_flag=1;} //如果超过5次不成功则释放总线
                  else
                  {STO=1;STA=1;}
                  break; //确认查询重复,置位STO+STA。
                  case 0x50: //主接收器:数据字节收到,ACK已发出;读SMB0DAT,等待
                  iic_read_buf[iic_receive_count++]=SMB0DAT;
                  iic_receive_len--;
                  if(iic_receive_len<2)AA=0; //下一个字节,如下一个字节是最后字节,清除AA。
                  break;
                  case 0x58: //主接收器:数据字节收到,NACK已发出,置位STO。
                  iic_read_buf[iic_receive_count++]=SMB0DAT; 
                  //读操作已经完成,读数据寄存器并且发出STOP.
                  iic_receive_len--;
                  STO=1;sm_busy=0; //Free SMBus 
                  break;
                  default:
                  STO=1;sm_busy=0;iic_error_flag=1; //Reset communication. 
                  break;
                  }
                  SI=0; //clear interrupt flag
                  }

                  main()
                  {
                  disable_wdog();
                  init_sysclk();
                  init_ioport();
                  init_smbus();
                  EA=1;i=0;
                  init_pcf8563();
                  for(;;)
                  {
                  read_clock();
                  }

                  }



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -