看了很多IIC的程序,都是用延时来实现IIC的时序,请问怎样用Timer_A来实现呢?怎样读写?
这个一般用不着定时器的,延时就可以了。
void delay_xms(void)
{
WORD i;
for(i=0;i<800;i++);
_NOP();
}
void rw_I2C_start(void)
{
MY_PXSEL &=~(SCL+SDA+WP);
MY_PXDIR |=(SCL+SDA+WP);
MY_PXOUT &=~WP;
_NOP();
_NOP();
MY_PXOUT |=SDA;
_NOP();
_NOP();
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT &=~SDA;
_NOP();
_NOP();
MY_PXOUT &=~SCL;
}
void rw_I2C_stop(void)
{
MY_PXDIR |=SDA;
MY_PXOUT &=~SDA;
_NOP();
_NOP();
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT |=SDA;
}
BYTE r_I2C_byte(void)
{
BYTE i,j=0;
MY_PXDIR &=~SDA;
for(i=1;i<=8;i++)
{
MY_PXOUT |=SCL;
j <<=1;
if ((MY_PXIN&SDA)==SDA) j |=0x01;
MY_PXOUT &=~SCL;
_NOP();
}
MY_PXDIR |=SDA;
MY_PXOUT |=SDA;
_NOP();
_NOP();
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT &=~SDA;
_NOP();
_NOP();
MY_PXOUT &=~SCL;
return j;
}
WORD r_I2C_word(void)
{
BYTE i;
WORD j=0;
MY_PXDIR &=~SDA;
for(i=1;i<=16;i++)
{
MY_PXOUT |=SCL;
j <<=1;
if ((MY_PXIN&SDA)==SDA) j |=0x01;
MY_PXOUT &=~SCL;
_NOP();
}
MY_PXDIR |=SDA;
MY_PXOUT |=SDA;
_NOP();
_NOP();
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT &=~SDA;
_NOP();
_NOP();
MY_PXOUT &=~SCL;
return j;
}
//----------------------------------------
// 单字节I2C的写入。
void w_I2C_byte( BYTE nByte ) //read or write command (0xAF read; OxAE write)
{ //start + 1010xxx (read or write start)
BYTE i;
MY_PXDIR |=SDA;
for(i=1;i<=8;i++)
{
if ((nByte&0x80)==0x80) MY_PXOUT |=SDA;
else MY_PXOUT &=~SDA;
nByte <<=1;
_NOP();
_NOP();
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT &=~SCL;
_NOP();
_NOP();
}
MY_PXDIR &=~SDA;
MY_PXOUT |=SCL;
_NOP();
_NOP();
MY_PXOUT &=~SCL;
}
//----------------------------------------
// 设置E2PROM口线,使之进入低功耗。
void ee_port_set(void)
{
MY_PXDIR |=WP+SCL+SDA;
MY_PXOUT |=WP+SCL+SDA;
}
//----------------------------------------
// [*Ram_Addr]--
// [I2C_Addr1]-- I2C的器件地址
// [I2C_Addr2]-- I2C的内部读写地址
// [nLen]-- 读写地址的字节数
void r_I2C_bytes( BYTE *Ram_Addr, BYTE I2C_Addr1, WORD I2C_Addr2, BYTE nLen )
{
rw_I2C_start();
w_I2C_byte( I2C_Addr1 );
// w_I2C_byte( I2C_Addr2>>8 ); // address 0 >=24C64
w_I2C_byte( I2C_Addr2&0xFF ); // address 1
for( ; nLen>0; nLen-- )
{
rw_I2C_start(); // Current Address Read
w_I2C_byte( I2C_Addr1|1 );
(*Ram_Addr) = r_I2C_byte();
Ram_Addr++;
}
rw_I2C_stop();
ee_port_set();
}
//----------------------------------------
// [*Ram_Addr]--
// [I2C_Addr1]-- I2C的器件地址
// [I2C_Addr2]-- I2C的内部读写地址
// [nLen]-- 读写地址的字节数
void w_I2C_bytes( BYTE *Ram_Addr, BYTE I2C_Addr1, WORD I2C_Addr2, BYTE nLen )
{
rw_I2C_start();
w_I2C_byte( I2C_Addr1 ); // control byte
// w_I2C_byte( I2C_Addr2>>8 ); // address 0 >=24C64
w_I2C_byte( I2C_Addr2&0xFF ); // address 1
for( ; nLen>0; nLen-- )
{
w_I2C_byte( *Ram_Addr );
Ram_Addr++;
}
rw_I2C_stop();
delay_xms();
ee_port_set();
}
void r_I2C_words( WORD *Ram_Addr, BYTE I2C_Addr1, WORD I2C_Addr2 )
{
rw_I2C_start();
w_I2C_byte( I2C_Addr1 );
w_I2C_byte( I2C_Addr2&0xFF ); // address 1
rw_I2C_start(); // Current Address Read
w_I2C_byte( I2C_Addr1|1 );
(*Ram_Addr) = r_I2C_word();
rw_I2C_stop();
ee_port_set();
}
我也用延时做了一个程序,但有朋友说用延时占用了太多CPU资源,在延时时CPU就做不了其他的了,建议我用定时器来做,我是初学MSP430单片机的,所以有很多不懂,不知道该怎样用定时器来做,编了一段程序,但时序老是不对,要不就是SCL线出来一周期性的PWM波,不知道该怎样传输数据了,还请版主指教。
将延时改成定时器定时,不用中断吗,那这样岂不是同延时差不多,也没有节约CPU啊?请多多指教,非常感谢!
用定时器用中断方式不要用查询标志位的方式就行了,这样CPU就不占用了。