📄 iic_analog.c
字号:
/*************************************************************************\
** filename: iic.c
** author: rui
** creat date:2008/05/01
** version: 1.0
** modify record:
*************************************************************************/
#include "iic.h"
/****************type define*************************/
typedef unsigned char u_char;
enum {
FALSE,
TRUE,
ILLEGAL
};
/***************macro define*************************/
#define WAIT_SLAVE(time) {while((time-- > 0) && (!SCL));} //wait slave device
#define WRADDR(svnbits_addr) ((svnbits_addr << 1) & 0xfe)
#define RDADDR(svnbits_addr) ((svnbits_addr << 1) | 0x01)
/************************iic driver**************************************/
/**
* notice: you should ensure:
* 1. setup time of start and stop
* 2. setup time of data
* 3. bus free time between two operations
*
* so, always, it must have delay before "scl = 1", it needn't to delay after "scl = 0"
* because hold time can be zero.
*
* you should be warn when bus control right will be changed.
*
**/
static void start()
{
SCL = 1;
SDA = 1;
delay_5us();
SDA = 0;
delay_5us();
SCL = 0;
}
static void send_one_byte(u_char content)
{
u_char msb, cnt,tmp;
cnt = 8;
while (cnt > 0)
{
msb = (content & 0x80);
SDA = ((msb == 0x80) ? 1 : 0); //send from msb to lsb
delay_5us(); //setup time of data
SCL = 1;
tmp = 100;
WAIT_SLAVE(tmp);
delay_5us();
SCL = 0;
content = (content << 1);
cnt--;
}
SDA = 1; //give the right of bus control to slave device
}
static u_char wait_ack()
{
u_char cnt;
cnt = 100;
delay_5us();
SCL = 1;
WAIT_SLAVE(cnt);
delay_5us();
if (SCL != 1)
return ILLEGAL;
if (SDA == 0)
{
SCL = 0;
return TRUE;
}
else
{
SCL = 0;
return FALSE;
}
}
static u_char receive_one_byte()
{
u_char rcv_content, cnt, tmp;
cnt = 8;
rcv_content = 0;
while (cnt > 0)
{
delay_5us(); //setup time of data
SCL = 1;
tmp = 100;
WAIT_SLAVE(tmp);
delay_5us();
rcv_content <<= 1;
rcv_content |= ((SDA == 1) ? 0x01 : 0x00); //rcv from msb to lsb
SCL = 0;
cnt--;
}
return rcv_content;
}
static void send_ack()
{
SDA = 0;
delay_5us();
SCL = 1;
delay_5us();
SCL = 0;
SDA = 1; //release data line for slave device to use
}
static void send_nack()
{
SDA = 1;
delay_5us();
SCL = 1;
delay_5us();
SCL = 0;
}
static void stop()
{
SDA = 0;
delay_5us();
SCL = 1;
delay_5us(); //setup time of stop
SDA = 1;
delay_5us(); //ensure free time of bus > 4.7us between operation on iic twice
}
/*****************iic bus level driver*******************************/
static u_char send_data_to_iic(u_char num, u_char *piicdata, u_char flag_start, u_char flag_stop)
{
if (TRUE == flag_start)
{
start();
}
while (num > 0)
{
send_one_byte(*piicdata);
if (TRUE != wait_ack() )
{
stop();
return FALSE;
}
else
{
piicdata++;
num--;
}
}
if (TRUE == flag_stop)
stop();
return TRUE;
}
static void receive_data_from_iic(u_char num, u_char *paddr_data_save)
{
while (num > 1)
{
*paddr_data_save = receive_one_byte();
send_ack();
paddr_data_save++;
num--;
}
*paddr_data_save = receive_one_byte();
send_nack();
stop();
}
/***************************device level driver*******************/
u_char write_device_by_iic0(u_char svnbits_dev_addr, u_char *reg_addr, u_char num_addr, u_char *pcontent, u_char num_data)
{
u_char tmp;
u_char addr[3];
addr[0] = (svnbits_dev_addr << 1) & 0xfe;
addr[1] = *reg_addr;
addr[2] = *(reg_addr + 1);
if (2 == num_addr)
{
tmp = send_data_to_iic(3, (u_char *)addr, TRUE, FALSE); //send device address & register address
}
else if (1 == num_addr)
{
tmp = send_data_to_iic(2, (u_char *)addr, TRUE, FALSE);
}
else
{
return FALSE;
}
if (FALSE == tmp)
return FALSE;
tmp = send_data_to_iic(num_data, pcontent, FALSE, TRUE); //send data writed
if (FALSE == tmp)
return FALSE;
else
return TRUE;
}
u_char read_device_by_iic0(u_char svnbits_dev_addr, u_char *reg_addr, u_char num_addr, u_char *paddr_data_save, u_char num_data)
{
u_char tmp;
u_char addr[3];
addr[0] = (svnbits_dev_addr<< 1) & 0xfe;
addr[1] = *reg_addr;
addr[2] = *(reg_addr+1);
if (2 == num_addr)
{
tmp = send_data_to_iic(3, (u_char *)addr, TRUE, FALSE); //send device address & register address
}
else if (1 == num_addr)
{
tmp = send_data_to_iic(2, (u_char *)addr, TRUE, FALSE);
}
else
{
return FALSE;
}
if (FALSE == tmp)
return FALSE;
addr[0] = (svnbits_dev_addr << 1) | 0x01;
tmp = send_data_to_iic(1, (u_char *)addr, TRUE, FALSE); //send restart and read flag
if (FALSE == tmp)
return FALSE;
receive_data_from_iic(num_data, paddr_data_save);
return TRUE;
}
u_char iic_bus0_initial()
{
u_char tmp;
tmp = 0;
SCL = 1;
SDA = 1;
while (tmp < 9)
{
SCL = 0;
delay_5us();
SCL = 1;
delay_5us();
if (SDA == 1)
{
start();
break;
}
tmp++;
}
if (9 == tmp)
return FALSE;
else
{
stop(); //here maybe need modify
return TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -