📄 i2c.c
字号:
/*
Copyright 2003 Nasif Akand (nasif@yifan.net)
http://go.to/zipamp
http://zipamp.virtualave.net
This file is part of ZipAmp MP3 software.
ZipAmp is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ZipAmp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this code; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//This module performs I2C operations for ZipAmp
//Nasif Akand
//If using CodeVision then following includes aren't needed.
//#include "zcontrol.h"
//#include "zfat.h"
//#include "zata.h"
//#include "ztype.h"
#include "i2c.h"
//#include "<delay.h>" //CodeVision AVR internal delay routines
//I2C implementation for STA013
//Port D bit 7 (pin 17) is SDA output while bit 0 (pin 10) is input, Pin 16 is SCL
//SDA input is always at HighZ state. If this pin is pulled up or output high, STA013 will be damaged.
#define SDA PORTD.7
#define SCL PORTD.6
#define SDAIn PIND.0
#define Out DDRD.7=1
#define In DDRD.7=0
#define qDelay delay_us(3) //According to Phillips I2C specs in all modes..
#define delay delay_us(3) //..max I2C delay can be 5 micro seconds.
#define Read 0x87 //STA013 I2C Read address
#define Write 0x86 //STA013 I2C Write Address
void STA013Reset() {
DDRB.3=1; //Set bit3 to Output mode
PORTB.3=0; //Set to 0 for reset
delay_ms(500); //Wait
PORTB.3=1; //Set to 1
delay_ms(500); //Wait
}
unsigned char wait_Ack (void) {
//returns 1 if ACK was 0 (meaning transfer was successful). In I2C ACK=0 means success.
unsigned char t=1;
delay;
// Take clock high
SCL=1;
delay;
// Test of ACK
delay;
if (PIND.0) { /*test of SDA level, if high -> problem*/
t=0;
}
delay;
if (PIND.0) { /*test of SDA level, if high -> problem*/
t=0;
}
// Take clock back low
delay;
SCL=0;
delay;
return t;
}
unsigned char i2cReadAddress(unsigned char adr) {
//Returns data read from register given in adr.
//In most cases we don't have to worry about it. If we don't get ACK, try 10 times before giving up.
unsigned char data, try=0, ack;
do {
i2cStart(); //I2c start
ack=i2cSend(Write); //Send i2c write address
ack &=i2cSend(adr); //Send register address
i2cStart(); //i2c re-start
delay; //wait
ack &= i2cSend(Read); //Send i2c read address
data=i2cReceive(0); //Receive data without sending ACK
i2cStop(); //Stop
try++;
}
while ((ack==0)&&(try<10)); //try 10 times if failed
return data;
}
unsigned char i2cWriteAddress(unsigned char adr, unsigned char data) {
//Writes data to register adr.
//Returns 1 on successful write, tries 10 times before giving up.
unsigned char ack,try=0;
do {
i2cStart(); //Start
ack = i2cSend(Write); //Send i2c write address
ack &= i2cSend(adr); //Send register address
delay; //wait
ack &= i2cSend(data); //Send data
i2cStop(); //Stop
try++;
}
while ((ack==0)&&(try<10)); //give up after 10 tries
return ack;
}
void i2cInit() {
DDRD.7=1; //Set to output mode for SDA
DDRD.6=1; //Set to output mode for SCL
}
void i2cStart() {
//I2C start condition.
DDRD.7=1; //SDA output mode
SDA=1;
delay;
SCL=1;
delay;
SDA=0;
delay;
SCL=0;
}
unsigned char i2cSend(unsigned char value){
//Sends byte value, and returs ACK from STA013, 1=Success, 0=Fail
unsigned char i;
DDRD.7=1;
for (i=0; i<8; i++) {
DDRD.7=1;
if (((value >> (7-i)) & 0x01)==0x01) SDA=1; //Send bit by bit
else SDA=0;
SCL=1;
delay;
SCL=0;
DDRD.7=1;
SDA=1;
delay;
}
delay;
i=wait_Ack();
return i;
}
unsigned char i2cReceive(unsigned char ack) {
//Receives data byte. Sends back acknoledge if ack is true
unsigned char value=0,i;
DDRD.7=1;
SDA=1;
for (i=0; i<8; i++) {
delay;
SCL=1;
delay;
value = (value << 1) + PIND.0; //leftshift previous value and add one more bit that's read
delay;
SCL=0;
}
if (ack) { //send ack if requested
DDRD.7=1;
SDA=0;
delay;
SCL=1;
delay;
SCL=0;
}
return value;
}
void i2cStop(){
//I2C stop condition.
delay;
DDRD.7=1; //SDA output mode
SDA=0;
delay;
SCL=1;
delay;
SDA=1;
delay;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -