📄 samtwi.c
字号:
#include "AT91SAM7S128.h"
#include "lib_at91sam7s128.h"
#include "SAMtwi.h"
#include "SAMpioc.h"
void TWIinit(void)
{
// clock
AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TWI); // TWI
// pin
AT91C_BASE_PIOA->PIO_PDR = (1<<4)|(1<<3);
AT91C_BASE_PIOA->PIO_ASR = (1<<4)|(1<<3); // PA4:TWCK , PA3:TWD
AT91C_BASE_PIOA->PIO_MDER = (1<<4)|(1<<3); // open drain
AT91C_BASE_PIOA->PIO_PPUDR= (1<<4)|(1<<3); // pull-up R
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_SWRST; // SW reset
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_MSEN; // TWI enable
//AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(1497<<8)|(1497); // 错!1497超出了8位的范围。about 8kHz @ 48MHz
//AT91C_BASE_TWI->TWI_CWGR=(3<<16)|(255<<8)|(255); //about 12kHz
AT91C_BASE_TWI->TWI_CWGR=(4<<16)|(180<<8)|(180); //about 8kHz
// AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(150<<8)|(150); //about 80khz
// AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(200<<8)|(200);//about 60KHz
// AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(120<<8)|(120);//about 100KHz
AT91C_BASE_TWI->TWI_IDR=0xFFFFFFFF;
}
void TWIsend(unsigned char mode,unsigned short addr,unsigned char *dat,unsigned char size)
{
unsigned int s=0;
char tmp;
if(!size) return; // size = 0
//AT91C_BASE_TWI->TWI_CR=0x04; // TWI enable
tmp = mode&0xf0 ;
if(tmp == 0xa0)
{
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(120<<8)|(120);//about 100KHz
}
else if(tmp == 0x70) //7290
{
AT91C_BASE_TWI->TWI_CWGR=(4<<16)|(180<<8)|(180); //about 8kHz
}
else if(tmp == 0x90) //ads1110
{
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(150<<8)|(150); //about 80khz
}
Delay(200);
if((mode&0x01)==0x00)
{
AT91C_BASE_TWI->TWI_MMR=(mode<<15)|(1<<8);
AT91C_BASE_TWI->TWI_IADR=addr&0x00FF;
}
else
{
AT91C_BASE_TWI->TWI_MMR=((mode&0xFE)<<15)|(2<<8);
AT91C_BASE_TWI->TWI_IADR=addr;
}
/*
s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START;
while(size-->1)
{
while(!(s&AT91C_TWI_TXRDY)) s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
}
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP; // TWI STOP
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) s=AT91C_BASE_TWI->TWI_SR;
*/
// in single byte... (datasheet page285)
if(1==size)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_STOP | AT91C_TWI_MSEN;
AT91C_BASE_TWI->TWI_THR=*dat;
}
// multiple bytes
else
{
s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
AT91C_BASE_TWI->TWI_CR=1; // TWI START
while((size--)>1)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_MSEN;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXRDY)) s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
}
// last byte
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP; // TWI STOP
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXRDY)) s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*dat;
}
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) s=AT91C_BASE_TWI->TWI_SR;
//AT91C_BASE_TWI->TWI_CR=0x08; // TWI disable
}
void ADCsend_By_TWI(unsigned char mode,unsigned short addr,unsigned char *dat,unsigned char size)
{
unsigned int s=0;
char tmp;
if(!size) return; // size = 0
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(150<<8)|(150); //about 80khz
Delay(200);
//AT91C_BASE_TWI->TWI_CR=0x04; // TWI enable
{
AT91C_BASE_TWI->TWI_MMR=(mode<<15)|(0<<12)|(0<<8);
AT91C_BASE_TWI->TWI_IADR=addr&0x00FF;
}
// in single byte... (datasheet page285)
if(1==size)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_STOP | AT91C_TWI_MSEN;
AT91C_BASE_TWI->TWI_THR=*dat;
}
// multiple bytes
else
{
s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
AT91C_BASE_TWI->TWI_CR=1; // TWI START
while((size--)>1)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_MSEN;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXRDY)) s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*(dat++);
}
// last byte
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP; // TWI STOP
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXRDY)) s=AT91C_BASE_TWI->TWI_SR;
AT91C_BASE_TWI->TWI_THR=*dat;
}
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) s=AT91C_BASE_TWI->TWI_SR;
//AT91C_BASE_TWI->TWI_CR=0x08; // TWI disable
}
void ADCread_By_TWI(unsigned char mode,unsigned short addr,unsigned char *dat,unsigned char size)
{
unsigned int s=0;
unsigned int i=0;
char tmp;
if(!size) return; // size = 0
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(150<<8)|(150); //about 80khz
Delay(200);
//AT91C_BASE_TWI->TWI_CR=0x04; // TWI enable
{
AT91C_BASE_TWI->TWI_MMR=(mode<<15)|(1<<12)|(0<<8);
AT91C_BASE_TWI->TWI_IADR=addr&0x00FF;
}
// in single byte... (datasheet page285)
if(1==size)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_STOP;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) s=AT91C_BASE_TWI->TWI_SR;
*dat= AT91C_BASE_TWI->TWI_RHR;
}
// multiple bytes
else
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_MSEN;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) // wait for stop
{
if(++i>=0x10000)
{
break;
}
//AT91F_US_PutChar ((AT91PS_USART) AT91C_BASE_DBGU,0xa1);
s=AT91C_BASE_TWI->TWI_SR;
if(s&AT91C_TWI_RXRDY)
{
*dat=AT91C_BASE_TWI->TWI_RHR;
// AT91F_US_PutChar ((AT91PS_USART) AT91C_BASE_DBGU,*dat);
dat++;
size--;
// last byte
if(1==size) AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP;
}
}
}
//AT91C_BASE_TWI->TWI_CR=0x08; // TWI disable
}
void TWIread(unsigned char mode,unsigned short addr,unsigned char *dat,unsigned char size)
{
unsigned int s=0;
unsigned int i = 0;
char tmp;
if(!size) return;
tmp = mode&0xf0 ;
if(tmp == 0xa0)
{
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(120<<8)|(120);//about 100KHz
}
else if(tmp == 0x70) //7290
{
AT91C_BASE_TWI->TWI_CWGR=(4<<16)|(180<<8)|(180); //about 8kHz
}
else if(tmp == 0x90) //ads1110
{
AT91C_BASE_TWI->TWI_CWGR=(1<<16)|(150<<8)|(150); //about 80khz
}
Delay(200);
//AT91C_BASE_TWI->TWI_CR=0x04; // TWI enable
if((mode&0x01)==0x00)
{
AT91C_BASE_TWI->TWI_MMR=(mode<<15)|(1<<12)|(1<<8);
AT91C_BASE_TWI->TWI_IADR=addr&0x00FF;
}
else
{
AT91C_BASE_TWI->TWI_MMR=((mode&0xFE)<<15)|(1<<12)|(2<<8);
AT91C_BASE_TWI->TWI_IADR=addr;
}
/*
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START;
s=AT91C_BASE_TWI->TWI_SR;
while(size-->1)
{
while(!(s&AT91C_TWI_RXRDY)) s=AT91C_BASE_TWI->TWI_SR;
*(dat++)=AT91C_BASE_TWI->TWI_RHR;
*(dat)=s;
}
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_RXRDY)) s=AT91C_BASE_TWI->TWI_SR;
*dat=AT91C_BASE_TWI->TWI_RHR;
*/
// single byte
if(1==size)
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_STOP;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) s=AT91C_BASE_TWI->TWI_SR;
*dat= AT91C_BASE_TWI->TWI_RHR;
}
// multiple bytes
else
{
AT91C_BASE_TWI->TWI_CR=AT91C_TWI_START | AT91C_TWI_MSEN;
s=AT91C_BASE_TWI->TWI_SR;
while(!(s&AT91C_TWI_TXCOMP)) // wait for stop
{
if(++i>=0x10000)
{
break;
}
s=AT91C_BASE_TWI->TWI_SR;
if(s&AT91C_TWI_RXRDY)
{
*(dat++)=AT91C_BASE_TWI->TWI_RHR;
size--;
// last byte
if(1==size) AT91C_BASE_TWI->TWI_CR=AT91C_TWI_STOP;
}
}
}
//AT91C_BASE_TWI->TWI_CR=0x08; // TWI disable
}
/*************************************************************************
ads1110 i2c driver
*************************************************************************/
void I2C_IOinit() //改iic外设由io控制
{
AT91F_PIOA_CfgPMC();//配置io口时钟
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,I2C_SETOUT);
SCL_IS_L;
SDA_IS_H;
Delay(DLY4);
}
void I2C_Start()
{
SDA_IS_H;
Delay(DLY4);
SCL_IS_H;
Delay(DLY4);
SDA_IS_L;
Delay(DLY4);
Delay(DLY4);
SCL_IS_L;
}
void I2C_Stop()
{
SDA_IS_OUT;
SDA_IS_L;
Delay(DLY4);
SCL_IS_H;
Delay(DLY4);
SDA_IS_H;
Delay(DLY4);
TWIinit(); //恢复iic外设
}
char I2C_WrByte(char x)
{
int i;
char tmp;
tmp = x;
SCL_IS_L;
SDA_IS_OUT;
Delay(DLY4);
for(i=0;i<8;i++)
{
if(tmp&0x80 == 0x80)
{
SDA_IS_H;
}
else
{
SDA_IS_L;
}
Delay(DLY2);
SCL_IS_H;
Delay(DLY4);
SCL_IS_L;
tmp = tmp<<1;
Delay(DLY4);
}
SDA_IS_IN;
SCL_IS_H;
Delay(DLY4);
if(AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SDA)
tmp = 1; //返回1,错误的应答
else
tmp = 0; //返回0,正确的应答
SCL_IS_L;
return(tmp);
}
char I2C_ReByte(char ask)
{
int i;
char tmp = 0;
SDA_IS_IN;
Delay(DLY4);
for(i=0;i<8;i++)
{
tmp=tmp<<1;
SCL_IS_H;
Delay(DLY4);
if(AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SDA)
{
tmp += 1;
}
SCL_IS_L;
Delay(DLY4);
}
SDA_IS_OUT;
if(ask)
{
SDA_IS_H;//若为1,表示不希望再接收数据,发送停止信号。接收完毕
}
else
{
SDA_IS_L;//ASK为0表示希望继续接收数据。
}
Delay(DLY4);
SCL_IS_H;
Delay(DLY4);
SCL_IS_L;
return(tmp);
}
/*************************************************************************
eepot x9241 drive
*************************************************************************/
unsigned char read_eepot_wiper ( char address )
{
unsigned char i ,baddr,saddr;
if(address >=4)
{
baddr = EEPOT_ADDR1;
saddr = EEPOT_RWCR | ((address - 4)<<2);
}
else
{
baddr = EEPOT_ADDR0;
saddr = EEPOT_RWCR | ((address)<<2);
}
TWIread(baddr,saddr,&i,1);
return(i);
}
int write_eepot_wiper( char a, char d )
{
unsigned char baddr,saddr;
if(a >=4)
{
baddr = EEPOT_ADDR1;
saddr = EEPOT_WWCR | ((a - 4)<<2);
}
else
{
baddr = EEPOT_ADDR0;
saddr = EEPOT_WWCR | ((a)<<2);
}
TWIsend(baddr,saddr,&d,1);
return(1);
}
void write_eepot_inc(char a)
{
unsigned char baddr,saddr;
unsigned char d;
if(a >=4)
{
baddr = EEPOT_ADDR1;
saddr = EEPOT_SKIP | ((a - 4)<<2);
}
else
{
baddr = EEPOT_ADDR0;
saddr = EEPOT_SKIP | ((a)<<2);
}
d= 0xff;
TWIsend(baddr,saddr,&d,1);
}
void write_eepot_dec(char a)
{
unsigned char baddr,saddr;
unsigned char d;
if(a >=4)
{
baddr = EEPOT_ADDR1;
saddr = EEPOT_SKIP | ((a - 4)<<2);
}
else
{
baddr = EEPOT_ADDR0;
saddr = EEPOT_SKIP | ((a)<<2);
}
d= 0x00;
TWIsend(baddr,saddr,&d,1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -