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

📄 mcs51-项目开发经典.c

📁 本人自己写的经典51程序完全好用。包括7279
💻 C
📖 第 1 页 / 共 5 页
字号:
// 函数功能:I2C总线启动
void i2c_start(void)
{ SCL=0;i2c_delay();//SDA只能在SCL为低时改变
  SDA=1;i2c_delay();
  SCL=1;i2c_delay();//SCL=1,SDA产生下降沿,则I2C启动
  SDA=0;i2c_delay();
  SCL=0;i2c_delay();//总线启动后时钟线为低,数据线为高
  SDA=1;i2c_delay();
}
//-------------------------------------------------------------------------------------------------
// 函数功能:I2C总线停止
void i2c_stop(void)
{ SCL=0;i2c_delay();//SDA只能在SCL为低时改变
  SDA=0;i2c_delay();
  SCL=1;i2c_delay();//SCL=1,SDA产生上升沿,则I2C停止
  SDA=1;i2c_delay();
  SCL=0;i2c_delay();//总线停止后时钟线为低,数据线为高
}
//-------------------------------------------------------------------------------------------------
// 函数功能:I2C的8位写
void i2c_send8bit(uchar shu)
{ uchar i;
  for(i=0;i<8;i++)
    {SDA=(bit)(shu&0x80);i2c_delay();
     shu=shu<<1;
     SCL=1;i2c_delay();
     SCL=0;i2c_delay();}
  SDA=1;i2c_delay(); //数据线做读入准备
  i2c_response_signal=SDA;i2c_delay();//读取应答信号
  SCL=1;i2c_delay(); //发送读取时钟信号
  SCL=0;i2c_delay();
}
//-------------------------------------------------------------------------------------------------
// 函数功能:I2C的8位读
uchar i2c_read8bit(void)
{ uchar i;
  uchar ddate=0;
  //SCL=0;//时钟线做读入准备
  //SDA=1;//数据线做读入准备
  //这两句是为了说明操作I2C总线的一个较让人迷惑的问题。本函数是I2C的8位读函数,
  //SDA即单片机的P34脚,必须置1作为输入,而SDA置1之前,I2C总线要求SCL必须为0,否则
  //I2C总线复位,所以才有这两句。为何屏蔽仍旧好使呢?因为程序中在调用i2c_read8bit()
  //这个函数之前调用了i2c_send8bit()函数,而i2c_send8bit()函数调用结束退出时SDA和
  //SCL的状态恰好已经是1和0。网上的很多I2C程序加了很多无畏的语句就是因为没很好的处
  //理这个问题!
  for(i=0;i<8;i++)
    {ddate<<=1;
     SCL=1;i2c_delay();
     ddate|=SDA;i2c_delay();
     SCL=0;i2c_delay();
	}
  return ddate;
}
//-------------------------------------------------------------------------------------------------
// 函数功能:I2C应答
void i2c_ack(void)
{ SCL=0;i2c_delay();
  SDA=0;i2c_delay(); //SDA=0应答,
  SCL=1;i2c_delay();
  SCL=0;i2c_delay();
  SDA=1;i2c_delay();
}
//=================================================================================================
// 24C02驱动程序
//=================================================================================================
// 函数功能:I2C总线器件24C02的单字节写入
// 形参:data_addr表示要写入的地址、data_write表示要写入的数据
void sendbyte_24c02(uchar data_addr,uchar data_write)
{ i2c_start();
  i2c_send8bit(0xA0);
  i2c_send8bit(data_addr);
  i2c_send8bit(data_write);
  i2c_stop();
  while(1)//应答查询,判断写操作完成
    {i2c_response_signal=1;
	 i2c_start();
     i2c_send8bit(0xA0);
     if(i2c_response_signal==0) break;
    }
}
//-------------------------------------------------------------------------------------------------
// 函数功能:I2C总线器件24C02的单字节读取
// 形参:data_addr表示要读取数据的存储地址
uchar readbyte_24c02(uchar data_addr)
{ uchar return_data;
  i2c_start();
  i2c_send8bit(0xA0);
  i2c_send8bit(data_addr);
  i2c_start();
  i2c_send8bit(0xA1);
  return_data=i2c_read8bit();
  i2c_stop();
  return (return_data);
}
//=================================================================================================
// SD2000驱动程序
//=================================================================================================
// SD2000读出和写入的时间数据必须是BCD码格式
// 举例:2007年、5月、23日、星期3、11时、34分、18秒 的具体表示方法如下:
// year  =0x04;
// month =0x02;
// date  =0x21;
// week  =0x06;
// hour  =0x15;
// minute=0x04;
// second=0x00;
//-------------------------------------------------------------------------------------------------
// 函数功能:时钟数据高低位调换,这是SD2000A芯片操作的唯一麻烦
uchar reverse_byte_hl(uchar clock_data)
{ bit temp_bit;
  bit_byte=clock_data;
  temp_bit=bit_byte_0;
  bit_byte_0=bit_byte_7;
  bit_byte_7=temp_bit;
  temp_bit=bit_byte_1;
  bit_byte_1=bit_byte_6;
  bit_byte_6=temp_bit;
  temp_bit=bit_byte_2;
  bit_byte_2=bit_byte_5;
  bit_byte_5=temp_bit;
  temp_bit=bit_byte_3;
  bit_byte_3=bit_byte_4;
  bit_byte_4=temp_bit;
  bit_byte=bit_byte;//important
  return (bit_byte);
}
//-------------------------------------------------------------------------------------------------
// 函数功能:设定SD2000A状态及时间写入
void set_sd2000(void)
{ i2c_start();
  i2c_send8bit(0x60);//发送SD2000A复位命令
  i2c_stop();
  i2c_start();
  i2c_send8bit(0x62);//发送写SD2000A状态寄存器命令
  i2c_send8bit(reverse_byte_hl(0xc0));//24小时进制,关所有中断输出
  i2c_stop();

  i2c_start();
  i2c_send8bit(0x64);//发送写时钟数据1命令
  i2c_send8bit(reverse_byte_hl(year));
  i2c_send8bit(reverse_byte_hl(month));
  i2c_send8bit(reverse_byte_hl(date));
  i2c_send8bit(reverse_byte_hl(week));
  i2c_send8bit(reverse_byte_hl(hour));
  i2c_send8bit(reverse_byte_hl(minute));
  i2c_send8bit(reverse_byte_hl(second));
  i2c_stop();
}
//-------------------------------------------------------------------------------------------------
// 函数功能:从SD2000A读取当前时间,从年到秒
void read_sd2000_ys(void)
{ i2c_start();
  i2c_send8bit(0x65);//发送"读时钟数据1"命令
  year=i2c_read8bit();
  i2c_ack();
  month=i2c_read8bit();
  i2c_ack();
  date=i2c_read8bit();
  i2c_ack();
  week=i2c_read8bit();
  i2c_ack();
  hour=i2c_read8bit();
  i2c_ack();
  minute=i2c_read8bit();
  i2c_ack();
  second=i2c_read8bit();
  i2c_stop();
  year  =reverse_byte_hl(year);
  month =reverse_byte_hl(month);
  date  =reverse_byte_hl(date);
  week  =reverse_byte_hl(week);
  hour  =reverse_byte_hl(hour)&0x7f;//调整hour数据
  minute=reverse_byte_hl(minute);
  second=reverse_byte_hl(second);
}
//=================================================================================================
// 串口UART操作相关程序
//=================================================================================================
//函数功能:串口发射1个字节
void uart_byte_out(uchar uart_data_out)
{ SBUF = uart_data_out;
  while(TI==0);
  TI=0;
}
//-------------------------------------------------------------------------------------------------
//函数功能:串口发射字符数组。通常将要发送的字符数组定义在CODE代码区。
void uart_string_out(char * char_array)
{  uchar i;
   for(i=0; i<strlen(char_array) ;i++)
     {
	  uart_byte_out(char_array[i]);
	 }
}
//-------------------------------------------------------------------------------------------------
//函数功能:串口输出数据十进制到PC机屏幕上
//形参:范围 0-65535 ;例如:data_to_out=12345(或0x3039),则计算机屏幕就显示12345
void uart_data_decimalist_out(uint data_to_out)
{  bit   entrance;
   uchar ge,shi,bai,qian,wan;
   wan  = (data_to_out/10000)     ;//拆分万位,并转化为ASKII码
   qian = (data_to_out%10000)/1000;//拆分千位,并转化为ASKII码
   bai  = (data_to_out%1000)/100  ;//拆分百位,并转化为ASKII码
   shi  = (data_to_out%100)/10    ;//拆分十位,并转化为ASKII码
   ge   = (data_to_out%10)        ;//拆分个位,并转化为ASKII码
   entrance=1;//开放个、十、百、千、万的判断传输入口
   if(wan && entrance)
     {uart_byte_out(change_hex_to_askii(wan));
	  uart_byte_out(change_hex_to_askii(qian));
	  uart_byte_out(change_hex_to_askii(bai));
	  uart_byte_out(change_hex_to_askii(shi));
	  uart_byte_out(change_hex_to_askii(ge));
	  entrance=0;//如果万位不为0,则不再判断其它位
	 }
   else if(qian && entrance)
     {uart_byte_out(change_hex_to_askii(qian));
	  uart_byte_out(change_hex_to_askii(bai));
	  uart_byte_out(change_hex_to_askii(shi));
	  uart_byte_out(change_hex_to_askii(ge));
	  entrance=0;//如果千位不为0,则不再判断其它位
	 }
   else if(bai && entrance)
     {uart_byte_out(change_hex_to_askii(bai));
	  uart_byte_out(change_hex_to_askii(shi));
	  uart_byte_out(change_hex_to_askii(ge));
	  entrance=0;//如果百位不为0,则不再判断其它位
	 }
   else if(shi && entrance)
     {uart_byte_out(change_hex_to_askii(shi));
	  uart_byte_out(change_hex_to_askii(ge));
	  entrance=0;//如果十位不为0,则不再判断其它位
	 }
   else
     {uart_byte_out(change_hex_to_askii(ge));
	 }
}
//-------------------------------------------------------------------------------------------------
// 函数功能:串口显示的回车换行
// 形参:newline_number 表示一共换几行
void uart_newline(uchar newline_number)
{ uchar i;
  for(i=0;i<newline_number;i++)
     {
	  uart_byte_out(0x0d);
      uart_byte_out(0x0a);
	 }
}
//-------------------------------------------------------------------------------------------------
// 函数功能:串口显示的空格
// 形参:space_number 表示空几个格
void uart_space(uchar space_number)
{ uchar i;
  for(i=0;i<space_number;i++)
     {
	  uart_byte_out(0x20);
	 }  
}
//=================================================================================================
// CSI93C46操作子程序
// 注意:这里使用的CSI93C46为16位结构的EEROM 
//=================================================================================================
/***********************************************************************/ 
/*名称: START_93C46()
/*说明: 用于93C46的启动,防止由于CS_93C46的改动而引起数据时序混乱
/***********************************************************************/ 
void START_93C46() 
  {uint num=1000;    
   DO_93C46=1;      /*防止DO由于是低电平而无法输入*/ 
   CS_93C46=1; 
   /*开启93C46*/ 
   CS_93C46=0; 
   DI_93C46=0; 
   SK_93C46=0; 
   CS_93C46=1; 
   while(num!=0){num=num-1;} 
  } 
/***************************************************************************/ 
/*名称:END_93C46()             */ 
/*说明:用于93C46的结束,防止由于CS_93C46的改动而引起数据线为0而无法输入*/ 
/***************************************************************************/ 
void END_93C46() 
  { 
   CS_93C46=0; 
   DI_93C46=1; 
   SK_93C46=1; 
  } 
 
/***********************************************************************/ 
/*名称:SEND_DATA_93C46()          */ 
/*说明:在93C46启动下,送入指定位数的数据       */ 
/*输入: op_data 要输入的数据          */ 
/*      num   输入的位数          */  
/**********************************************************************/ 
void SEND_DATA_93C46(unsigned int op_data,unsigned char num) 
  {data unsigned char temp1; 
   op_data=op_data<<(16-num);    /*左移去掉无用位*/ 
   for(temp1=0;temp1<num;temp1++) 
      {if( (op_data&0X8000)==00 ){DI_93C46=0;} 
       else{DI_93C46=1;} 
       SK_93C46=1;SK_93C46=1;SK_93C46=1;SK_93C46=1; 
       SK_93C46=0; 
       op_data=op_data<<1; 
      } 
  } 
 
/***********************************************************************/ 
/*名称: EWEN_93C46()           */ 
/*说明: 93C46的编程启动.操作码(100  11XXXX)      */ 
/***********************************************************************/ 
void EWEN_93C46() 
  { 
   START_93C46(); 
   SEND_DATA_93C46(0X04,0X03);     /*送入3位操作码*/ 
   SEND_DATA_93C46(0X30,0X06);     /*送入6位地址*/ 
   END_93C46();  

⌨️ 快捷键说明

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