?? hard_i2c._c
字號:
/****************************************Copyright (c)**************************************************
** ADEmbed Development Co.,LTD.
** http://www.adembed.com
**--------------File Info-------------------------------------------------------------------------------
** File name: 24c02.c
** Last modified Date: 2008-12-13
** Last Version: 1.0
** Descriptions: 24c02 Test.
**
**------------------------------------------------------------------------------------------------------
** Created by: junbolu
** Created date: 2008-12-13
** Version: 1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
**ICC-AVR application builder : 2008-12-13
**Target : M16
**Crystal: 7.3728Mhz
**PC0--->SCL PC1--->SDA PD6--->Write_EN
**
**描述:按鍵K0被按下一次,數碼管的最低位會加一,并存儲在24C02中,下一次系統啟動時,會讀取此數據并顯示。
** 此程序采用的硬件I2C方式完成的24C02的讀寫。
**
**涉及知識點:
** 硬件I2C
**
**
*******************************************************************************************************/
#include<iom16v.h>
#include<macros.h>
#include"Define.h"
#define fose 7372800
#define SCL 0
#define SDA 1
#define i2c_ddr DDRC
#define i2c_port PORTC
#define i2c_pin PINC
#define AT24C02_ADDR 0xA0 //EEPROM設備地址
//定義I2C的延遲參數
#define DelayX 100 //7.3M=>1; 8.4M=>2.建議5,因為將來的ClockCPU可以是16M
#define SCL_1 {i2c_port|=1<<SCL;Delay_us(DelayX);}
#define SCL_0 {i2c_port&=~(1<<SCL);Delay_us(DelayX);}
#define SDA_1 {i2c_port|=1<<SDA;Delay_us(DelayX);}
#define SDA_0 {i2c_port&=~(1<<SDA);Delay_us(DelayX);}
#define Write_EN_DO DDRD |= (1<<6);
#define Write_EN_1 PORTD|= (1<<6);
#define Write_EN_0 PORTD&=~(1<<6);
#define rd_device_add 0xa1
#define wr_device_add 0xa0
//TWI狀態定義
//MT 主方式傳輸 MR 主方式接收
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
//常用TWI操作(主模式寫和主模式讀)
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait() {while(!(TWCR&(1<<TWINT)));}
#define TestAck() (TWSR&0xf8)
#define SetAck() (TWCR|=(1<<TWEA))
#define SetNoAck() (TWCR&=~(1<<TWEA))
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN))
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
unsigned char DISP_NUM; //顯示的位數
unsigned char BitTab[]={0xFE,0xFD,0xFB,0xF7}; //三位位選碼
unsigned char DispTab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //LED字形碼
unsigned char DISP_DATA[4]={0,0,0,0}; //顯示的數字
void I2C_Ini(void);
unsigned char i2c_Write(unsigned char RomAddress,unsigned char Wdata);
unsigned char i2c_Read(unsigned char RomAddress);
void Delay_us(unsigned int time)
{
while(time--);
}
void Delay_ms(unsigned int time)
{
while(time--)
{
Delay_us(1000);
}
}
void INT0_Init()
{
GIFR |=0X40; //清楚標志位
//MCUCR|=0X03; //上升沿觸發中斷
MCUCR|=0X02;MCUCR&=~0X01; //下降沿觸發中斷
GICR |=0X40; //使能外部中斷0
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
DISP_DATA[3]++;
if(DISP_DATA[3]>9)
{
DISP_DATA[3]=0;
}
Write_EN_0;
i2c_Write(0x02,DISP_DATA[3]);
Write_EN_1;
}
//顯示函數,DISP_NUM決定顯示哪個LED
//采用共陰LED動態顯示方法,定時中斷函數里面調用
void Display(void)
{
PORTA=0x00; //清除顯示再位選
PORTB=BitTab[DISP_NUM]; //PB口接位選
PORTA=DispTab[DISP_DATA[DISP_NUM]]; //PA口接LED的段碼
DISP_NUM++; //先顯示高位,再顯示低位
if(DISP_NUM==4)
DISP_NUM=0;
}
#pragma interrupt_handler timer0comp:20
void timer0comp (void)
{
Display();
}
void main(void)
{
DDRA=0XFF;
PORTA=0X00;
DDRB=0X0F;
PORTB=0X00;
//按鍵0端口初始化
DDRD &=~0x04; //設置PD2為輸入
PORTD|=0x04; //設置PD2為上拉
INT0_Init(); //TART初始化
//t/c0初始化(10ms)
TCCR0=0X0d;
TCNT0=0X00;
OCR0=0X48;
TIMSK=0X02;
//asm("sei");
SEI(); //全局中斷使能
//I2C_Ini();
TWSR = 0X03; /* TWI clock prescaler (TWPS) value = 0 */
TWBR = 0X10;
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
Write_EN_DO;
Write_EN_1;
DISP_DATA[3]=i2c_Read(0x02);
for(;;)
{
}
}
//=======================================================================
//初始化端口
void I2C_Ini(void)
{
i2c_ddr|=(1<<SCL); //SCK為輸出
i2c_ddr|=(1<<SDA); //SDA為雙向的,先設置為輸出
}
/******************************************
I2C總線寫一個字節
返回1:寫成功
返回非1:寫失敗
*******************************************/
unsigned char i2c_Write(unsigned char RomAddress,unsigned char Wdata)
{unsigned char number=10;
while(number--)
{
Start();//I2C啟動
Wait();
if(TestAck()!=START) continue;//ACK
Write8Bit(wr_device_add);//寫I2C從器件地址和寫方式
Wait();
if(TestAck()!=MT_SLA_ACK)
{putchar(0);
continue;//ACK
}
Write8Bit(RomAddress);//寫24C02的ROM地址
Wait();
if(TestAck()!=MT_DATA_ACK) continue;//ACK
Write8Bit(Wdata);//寫數據到24C02的ROM
Wait();
if(TestAck()!=MT_DATA_ACK) continue;//ACK
break;
}
Stop();//I2C停止
Delay_ms(10);//延時10ms等EEPROM寫完
return 1;
}
/******************************************
I2C總線讀一個字節
*******************************************/
unsigned char i2c_Read(unsigned char RomAddress)
{char a=0x00;
unsigned char temp=0;
unsigned char number=10;
while(number--)
{
Start();//I2C啟動
Wait();
a=TestAck();
if (a!=START) continue;//ACK
Write8Bit(wr_device_add);//寫I2C從器件地址和寫方式
Wait();
if (TestAck()!=MT_SLA_ACK) continue;//ACK
Write8Bit(RomAddress);//寫STA013的ROM地址
Wait();
if (TestAck()!=MT_DATA_ACK) continue;
Start();//I2C重新啟動
Wait();
if (TestAck()!=RE_START) continue;
Write8Bit(rd_device_add);//寫I2C從器件地址和讀方式
Wait();
if(TestAck()!=MR_SLA_ACK) continue;//ACK
Twi();//啟動主I2C讀方式
Wait();
if(TestAck()!=MR_DATA_NOACK) continue;//ACK
temp=TWDR;//讀取I2C接收數據
break;
}
Stop();//I2C停止
return temp;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -