📄 lesson10.c
字号:
/*time1_interrupt段时间计数*/
/*************************************************/
void time1_interrupt(void) interrupt 3 using 0
{
uchar uc_device_addr,uc_device_sub_addr;
uchar j;
g_ui_timer1_interval_cnt ++;
if(g_ui_timer1_interval_cnt >= 600)//6000*0.1s=10min
{
TH1 = 0x3C ;//初值15536
TL1 = 0xB0 ;//100ms=0.1s
g_ui_timer1_interval_cnt = 0;//重新开始计数
g_uc_data_send[0] = g_st_current_time.min;
g_uc_data_send[1] = g_st_current_time.sec;
g_uc_data_send[2] = g_uc_log_number;
uc_device_addr = 0xA0;//0xA0=1010 0000B, 1010is the device number,000 is the A2A1A0 hard wired, 0 write.
uc_device_sub_addr = 0x00 + ((g_uc_time_interval + 1) << 3);//EEPROM 首地址
ISendStr(uc_device_addr,uc_device_sub_addr,g_uc_data_send,3);//以页方式存储
g_uc_time_interval ++;//时间段加1
g_uc_log_number = 0;//新的时间段开始,清除记录值
beep = 0;//连续发声
delay(100,100);
beep = 1;
}
if(g_uc_time_interval >= 7)
{
ET0 = 0;//禁止T0
ET1 = 0;
TR0 = 0;//停止T0
TR1 = 0;
EX0 = 0;//禁止外部中断0
beep = 0;
for(j = 0;j < 8;j++)//断续提示声
{
delay(200,200);
if(beep == 0)beep = 1;
else beep = 0;
}
}
}
/*************************************************/
/*int0_interrupt*/
/*************************************************/
void int0_interrupt(void) interrupt 0 using 1
{
beep = 0;//连续发声
delay(50,100);
beep = 1;
EX0 = 0;
g_uc_log_number ++;
if((g_uc_log_number&0x0F) > 9)//显示为10进制数,CD4511不能显示A~F
{
g_uc_log_number += 6;
}
delay(55,255);//在短时间内不相应那么多中断,//看产品下线的速度而定
//如果延时过多,应该给予时钟补偿,g_uc_sec_cnt+*
//g_st_current_time.sec += 2;//给时钟进行时间补偿2s//因为外部中断0自然优先级比timer0高
EX0 = 1;
}
/*************************************************/
/*serial_interrupt*/
/*************************************************/
void serial_interrupt(void) interrupt 4 using 2
{
EA = 0;
RI = 0;//软件清除中断标志
g_uc_recv_serial_cnt ++;
beep = 0;
delay(30,55);
beep = 1;
if(g_uc_recv_serial_cnt < 7)
{
ACC = SBUF;
//XBYTE[g_ui_ram_addr] = ACC;//不屏蔽掉,发ACC内容回PC时显示乱码
//g_ui_ram_addr ++;
//ACC = uc_temp_receive[g_uc_recv_serial_cnt][2] + 0x30;
//delay(5,200);
//delay(5,10);
//delay(5,0);//添加了延时后,无法把ACC中内容在PC上显示出字符
//SBUF = 0x21;//back to IBM, check the TI
SBUF = ACC;
//display_led(g_uc_data_receive[0],g_uc_data_receive[1],g_uc_data_receive[2]);
}
else
{
ACC = 0x2A;//ASCII 0x21:!
SBUF = ACC;
}
while(TI == 0)
{
delay(3,255);
}
TI = 0;
EA = 1;
}
/*************************************I2C start*****************************************/
/**********************************void Start_I2C()*********************************
该函数是启动总线函数,功能是启动I2C总线,即发送I2C起始条件
注意: 在SCL高电平时,SDA从高电平变低电平表示start;
在SCL高电平时,SDA从低电平变高电平表示stop。
*********************************************************************************/
void Start_I2C(void)
{
SDA = 1;//发送起始条件的数据信号
_Nop();
SCL = 1;
_Nop();//起始条件建立时间大于4.7us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 0;//发送起始信号
_Nop();//起始条件锁定时间大于4us
_Nop();
_Nop();
_Nop();
_Nop();
SCL = 0;//嵌住I2C总线准备发送或接收数据
_Nop();
_Nop();
}
/******************************************************************
该函数为结束总线函数,功能是结束I2C总线,即发送I2C结束条件
******************************************************************/
void Stop_I2C(void)
{
SDA = 0;//发送结束条件的数据信号
_Nop();
SCL = 1;//发送结束条件的时钟信号
_Nop();//结束条件建立时间大于4us
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 1;//发送I2C总线结束信号
_Nop();
_Nop();
_Nop();
_Nop();
}
/*********************void SendB(unsigned char c)*********************************
该函数为字节数据传送函数,功能是将数据c发送出去,可以是地址,也可以是数据,发送完毕后等待应答,
并对此状态位进行操作(不应答或非应答都使ack = 0,假)。发送数据正常ack = 1;ack = 0表示被控制
器无应答或损坏。
****************************************************************/
void SendB(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt = 0;BitCnt < 8;BitCnt++)//要传送的数据长度为8位
{
if((c<<BitCnt)&0x80)
SDA = 1;//判断发送位//判断需要发送的bit为0还是1
else
SDA = 0;
_Nop();
SCL = 1;//置时钟线为高,通知被控制器开始接收数据位
_Nop();
_Nop();//保证时钟高电平周期大于4us
_Nop();
_Nop();
_Nop();
SCL = 0;
}
_Nop();
_Nop();
SDA = 1;//8位发送完毕后,释放数据线准备接收应答位
_Nop();
_Nop();
SCL = 1;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
if(SDA == 1)
{
ack = 0;//判断是否接收到应答信号
}
else
ack = 1;
SCL = 0;
_Nop();
_Nop();
}
/***************************unsigned char RcvB()******************************
该函数是字节数据传送函数,功能:接收从器件传来的数据,并判断总线错误(不发应答信号),
发送完毕后调用应答函数。
************************************************************************/
unsigned char RcvB(void)
{
unsigned char retc;
unsigned char BitCnt;
retc = 0;
SDA = 1;
for(BitCnt = 0;BitCnt < 8;BitCnt++)
{
_Nop();
SCL = 0;//置时钟总线为低,准备接收数据
_Nop();
_Nop();//时钟低电平大于4us
_Nop();
_Nop();
_Nop();
SCL = 1;//置时钟总线为高,是数据线上数据有效
_Nop();
_Nop();
retc = retc << 1;
if(SDA == 1) retc = retc + 1;//读数据位,接收的数据位放入retc中
_Nop();
_Nop();
}
SCL = 0;
_Nop();
_Nop();
return(retc);
}
/***********************************void Ack_I2C(bit a)*********************************
该函数为应答函数,功能:主控制器进行应答信号(主机发送的应答信号)(对于从机的应答信号,主机只需要检测)
******************************************************************************************/
void Ack_I2C(bit a)
{
if(a == 0)
SDA = 0;//在此发出应答或非应答信号
else
SDA = 1;
_Nop();
_Nop();
_Nop();
SCL = 1;
_Nop();//时钟低电平周期大于4us
_Nop();
_Nop();
_Nop();
_Nop();
SCL = 0;//清时钟线,嵌住I2C总线以便接收
_Nop();
_Nop();
}
/******************************bit ISendB(unsigned char sla, unsigned char c)*********************************
该函数为无子地址器件发送字节数据函数,功能:从启动总线到发送地址、数据,结束总线的全过程,从器件地址sla,如果返回1,表示操作成功,否则操作有误。
*********************************************************************************************/
/*bit ISendB(unsigned char sla, unsigned char c)
{
Start_I2C();
SendB(sla);
if(ack == 0)
return(0);
SendB(c);
if(ack == 0)
return(0);
Stop_I2C();
return(1);
}
*/
/*******************************bit IRcvB(unsigned char sla, unsigned char *c)*****************************
该函数为向无子地址器件读字节数据函数,功能是从启动总线到发送地址、读数据,结束总线的全过程。
从器件地址sla返回值在c,如果返回1表示操作成功,否则操作有误。
*****************************************************************************************/
/*bit IRcvB(unsigned char sla, unsigned char *c)
{
Start_I2C();//启动总线
SendB(sla+1);//发送器件地址;LSB=1,读数据,LSB=0,写数据。
if(ack == 0)
return(0);
*c = RcvB();//读取数据
Ack_I2C(1);//发送非应答位
Stop_I2C();//结束总线
return(1);
}
*/
/*************bit ISendStr(unsigned char sla,unsigned char suba, unsigned char *s, unsigned char no)*****************************************
该函数为向有子地址器件发送多字节数据函数,功能是从启动总线到发送地址、子地址,数据结束总线的全过程,从器件地址sla,子地址suba。
发送内容是s指向的内容,发送no字节,如果返回1表示操作成功,否则操作有误。
注意: 不同的24CXX,no的最大值不用;对于24C01、24C02,按页写最大为8 bytes
对于24C04、08、16,按页写最大为16 bytes
向EEPROM写时,应答信号是从机在正确接收数据后,自动给出
***********************************************************************************************/
bit ISendStr(unsigned char sla, unsigned char suba, unsigned char * s,unsigned char no)
{
unsigned char i;
Start_I2C();//启动总线
SendB(sla);//发送器件地址
if(ack == 0)
return(0);
SendB(suba);//发送器件子地址
if(ack == 0)
return(0);
for(i=0;i<no;i++)
{
SendB(*s);//发送数据
if(ack == 0)return (0);
s++;
}
Stop_I2C();//结束总线
return(1);
}
/****************************bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)************************
该函数为向有子地址器件读取多字节数据函数,功能是从启动总线到发送地址、子地址,读数据,结束总线的全过程。
从器件地址sla、子地址suba,读取内容放入s指向的存储区,读no字节。如果返回1表示操作争取,否则表示操作有误。
注意: 读EEPROM24CXX时,应答信号是主机正确接收数据后发出
接收的最后一位数据,给出非应答信号
******************************************************************************************************/
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2C();//启动总线
SendB(sla);//发送器件地址
if(ack ==0)
return(0);
SendB(suba);//发送器件子地址
if(ack ==0)
return(0);
Start_I2C();
SendB(sla+1);//LSB=1,读数据,LSB=0,写数据。
if(ack ==0)
return(0);
for(i = 0;i< no-1;i++)
{
*s=RcvB();//发送数据
Ack_I2C(0);//主机发送应答位
s++;
}
*s = RcvB();
Ack_I2C(1);//发送非应答位。最后一位数据时,主机发送非应答信号。
Stop_I2C();//结束总线
return(1);
}
/************************************I2C End*********************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -