jlass 发表于 2013-3-7 10:31
SMI时序不对居多,特别是读写翻转的时候
void rtl_smi_delay(unsigned char t)
{
while(t--)
{
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
}
}
void rtl_smi_start()
{
SCK=0;
SDA=1;
rtl_smi_delay(5);
/* CLK 1: 0 -> 1, 1 -> 0 */
SCK=1;
rtl_smi_delay(5);
SCK=0;
rtl_smi_delay(5);
/* CLK 2: */
SCK=1;
rtl_smi_delay(5);
SDA=0;
rtl_smi_delay(5);
SCK=0;
//rtl_smi_delay(5);
//SDA=1;
}
void rtl_smi_stop()
{
rtl_smi_delay(5);
SDA=0;
SCK=0;
rtl_smi_delay(5);
SCK=1;
rtl_smi_delay(5);
SDA=1;
rtl_smi_delay(5);
SDA=0;
/* add a click */
rtl_smi_delay(5);
SDA=1;
SCK=0;
rtl_smi_delay(5);
SCK=1;
rtl_smi_delay(5);
SCK=0;
}
void rtl_smi_write_bits(unsigned char wtData, unsigned char len)
{
for (; len > 0; len--) {
SCK=0;
rtl_smi_delay(3);
/* prepare data */
SDA=!!(wtData & ( 1 << (len - 1)));
rtl_smi_delay(2);
/* clocking */
SCK=1;
rtl_smi_delay(5);
SCK=0;
}
}
void rtl_smi_read_bits(unsigned char len, unsigned char *rddata)
{
//gpio_direction_input(sda); SDA pin 设置为输入模式 P3M1=0;
P0M1=0x40;//高阻输入模式
P0M0=0x80;
SDA=1;
for (*rddata = 0; len > 0; len--) {
unsigned char u;
SCK=0;
rtl_smi_delay(5);
/* clocking */
SCK=1;
rtl_smi_delay(6);
u = SDA;
SCK=0;
*rddata |= (u << (len - 1));
}
//gpio_direction_input(sda); SDA pin 设置为输出模式 P3M1=1;用推挽模式
P0M1=0x00;//推挽输出模式
P0M0=0xC0;
}
unsigned char rtl_smi_wait_for_ack()
{
unsigned char retry_cnt;
retry_cnt = 0;
do {
unsigned char ack;
rtl_smi_read_bits(1, &ack);
if (ack == 0)
break;
if (++retry_cnt >15)
return 1;
} while (1);
return 0;
}
unsigned char rtl_smi_write_byte(unsigned char wtdata)
{
rtl_smi_write_bits(wtdata, 8);
return rtl_smi_wait_for_ack();
}
unsigned char rtl_smi_write_byte1(unsigned char wtdata)
{
rtl_smi_write_bits(wtdata, 8);
return 0;
}
unsigned char rtl_smi_read_byte0(unsigned char *rddata)//读之后应答结束
{
unsigned char t;
/* read data */
rtl_smi_read_bits(8, &t);
*rddata = (t & 0xff);
/* send an ACK */
rtl_smi_write_bits(0x00,1);
return 0;
}
unsigned char rtl_smi_read_byte1(unsigned char *rddata)//读之后非应答结束
{
unsigned char t;
/* read data */
rtl_smi_read_bits(8, &t);
*rddata = (t & 0xff);
/* send an ACK */
rtl_smi_write_bits(0x01,1);
return 0;
}
unsigned char rtl_smi_read_reg(unsigned int addr, unsigned int *rddata)
{
unsigned char lo = 0;
unsigned char hi = 0;
unsigned char ret;
i2dutype retdata,addrdata;
addrdata.intdata=addr;
rtl_smi_start();
/* send READ command */
ret = rtl_smi_write_byte(0x0B << 4 | 0x04 << 1 | 0x01);
LED1=0;
if (ret)
goto out;
LED2=0;
/* set ADDR[7:0] */
ret = rtl_smi_write_byte(addrdata.dudata.Ldata);
if (ret)
goto out;
/* set ADDR[15:8] */
ret = rtl_smi_write_byte(addrdata.dudata.Hdata);
if (ret)
goto out;
//rtl_smi_write_bits(0x00,1);
/* read DATA[7:0] */
rtl_smi_read_byte0(&lo);
/* read DATA[15:8] */
rtl_smi_read_byte1(&hi);
retdata.dudata.Hdata=hi;
retdata.dudata.Ldata=lo;
*rddata=retdata.intdata;
//*rddata = ((unsigned int ) lo) | (((unsigned int ) hi) << 8);
ret = 0;
out:
rtl_smi_stop();
return ret;
}
unsigned char rtl_smi_write_reg(unsigned int addr, unsigned int wtdata)
{
int ret;
rtl_smi_start();
/* send WRITE command */
ret = rtl_smi_write_byte(0x0B << 4 | 0x04 << 1 | 0x00);
if (ret)
goto out;
/* set ADDR[7:0] */
ret = rtl_smi_write_byte(addr & 0xff);
if (ret)
goto out;
/* set ADDR[15:8] */
ret = rtl_smi_write_byte(addr >> 8);
if (ret)
goto out;
/* write DATA[7:0] */
ret = rtl_smi_write_byte(wtdata & 0xff);
if (ret)
goto out;
/* write DATA[15:8] */
ret = rtl_smi_write_byte(wtdata >> 8);
if (ret)
goto out;
LED5=0;
ret = 0;
out:
rtl_smi_stop();
return ret;
}
|