1. 程式人生 > >硬體I2C(TWI)讀寫PCF8563和24CXX程式

硬體I2C(TWI)讀寫PCF8563和24CXX程式

//ICC-AVR application builder : 2010-3-5 13:51:50 
// Target : M88 
// Crystal: 8.0000Mhz 

#include <iom88v.h> 
#include <macros.h> 
#include <eeprom.h> 

//I2C(TWI)基本指令 
#define I2C_START()  TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTA) 
#define I2C_STOP()  TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTO) 
#define I2C_ACK()    TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWEA) 
#define I2C_NAK()    TWCR = BIT(TWINT)|BIT(TWEN) 
#define I2C_CHECK_STATUS(X)  {while(!(TWCR&BIT(TWINT))); if((TWSR&0xF8)!=(X)) return 0;} 
#define I2C_WRITE(X)  TWDR = (X) 
#define I2C_READ(X)    (X) = TWDR 

//TWSR&0xF8 狀態碼 
#define START        0x08 
#define RE_START      0x10 
#define MT_SLA_ACK    0x18 
#define MT_SLA_NAK    0x20 
#define MT_DATA_ACK  0x28 
#define MT_DATA_NAK  0x30 
#define SLA_DATA_FAIL 0x38 
#define MR_SLA_ACK    0x40 
#define MR_SLA_NAK    0x48 
#define MR_DATA_ACK  0x50 
#define MR_DATA_NAK  0x58 

//器件地址及引數 
#define SLA_R_24C64      0xA1 
#define SLA_W_24C64      0xA0 
#define PAGE_SIZE_24C64  32 
#define NUM_PAGE_24C64  256 

#define SLA_R_PCF8563    0xA3 
#define SLA_W_PCF8563    0xA2 
#define PAGE_SIZE_PCF8563 16 
#define NUM_PAGE_PCF8563  1 

//毫秒級延時 
void delay_ms(unsigned int x) 
{ 
int i,j; 
for(j=0;j<x;j++) 
for(i=0;i<1141;i++); 
} 

/************************************************************************ 
I2C主機寫N位元組資料到從器件 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明: 
SLA_W: 從器件寫地址 
ADDR:  從器件內部寫資料起始地址 
N:    寫資料位元組數 
DAT:  源資料起始地址 
************************************************************************/ 
unsigned char i2c_write_n_bytes(unsigned char SLA_W, unsigned int ADDR, 
unsigned int N, unsigned char *DAT) 
{ 
unsigned int i; 
I2C_START(); 
I2C_CHECK_STATUS(START); 

I2C_WRITE(SLA_W); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_SLA_ACK); 

if(SLA_W!=SLA_W_PCF8563) 
{ 
I2C_WRITE((unsigned char)ADDR>>8); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_DATA_ACK); 
} 
I2C_WRITE((unsigned char)ADDR); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_DATA_ACK); 

for(i=0;i<N;i++) 
{ 
I2C_WRITE(DAT); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_DATA_ACK); 
} 

I2C_STOP(); 
return 1; 
} 

/************************************************************************ 
I2C主機從從器件讀N位元組資料 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明: 
SLA_R: 從器件讀地址 
ADDR:  從器件內部讀資料起始地址 
N:    讀資料位元組數 
DAT:  目標資料起始地址 
************************************************************************/ 
unsigned char i2c_read_n_bytes(unsigned char SLA_R, unsigned int ADDR, 
unsigned int N, unsigned char *DAT) 
{ 
unsigned int i; 

I2C_START(); 
I2C_CHECK_STATUS(START); 

I2C_WRITE((SLA_R)-1); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_SLA_ACK); 

if(SLA_R!=SLA_R_PCF8563) 
{ 
I2C_WRITE((unsigned char)ADDR>>8); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_DATA_ACK); 
} 
I2C_WRITE((unsigned char)ADDR); 
I2C_NAK(); 
I2C_CHECK_STATUS(MT_DATA_ACK); 

I2C_START(); 
I2C_CHECK_STATUS(RE_START); 

I2C_WRITE(SLA_R); 
I2C_NAK(); 
I2C_CHECK_STATUS(MR_SLA_ACK); 

if(N>1) 
{ 
for(i=0;i<N-1;i++) 
{ 
I2C_ACK(); 
I2C_CHECK_STATUS(MR_DATA_ACK); 
I2C_READ(DAT); 
} 
} 
I2C_NAK(); 
I2C_CHECK_STATUS(MR_DATA_NAK); 
DAT[N-1]=TWDR; 

I2C_STOP(); 
return 1; 
} 


/************************************************************************ 
I2C主機檢測從器件忙 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明: 
SLA_W: 從器件寫地址 
器件忙返回 1,否則返回 0,用於判斷EEPROM是否程式設計完成 
************************************************************************/ 
unsigned char i2c_check_busy(unsigned char SLA_W) 
{ 
unsigned char retv=0; 
I2C_START(); 
I2C_CHECK_STATUS(START); 
I2C_WRITE(SLA_W); 
I2C_NAK(); 
while(!(TWCR&BIT(TWINT))); 
if((TWSR&0xF8)!=MT_SLA_ACK) retv=1; 
I2C_STOP(); 
return retv; 
} 

/************************************************************************ 
I2C主機寫N位元組資料到從器件(EEPROM) 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明: 
SLA_W:    從器件寫地址 
PAGE_SIZE: EEPROM頁大小(單位:位元組) 
NUM_PAGE:  EEPROM總頁數 
ADDR:      從器件內部寫資料起始地址 
N:        寫資料位元組數 
DAT:      源資料起始地址 
************************************************************************/ 
void SEEPROM_write_n_bytes(unsigned char SLA_W,unsigned int PAGE_SIZE,unsigned int NUM_PAGE, 
unsigned int ADDR,unsigned int N,unsigned char *DAT) 
{ 
unsigned int PAGE,END_PAGE,NBYTES[2],i; 
END_PAGE=(ADDR+N)/PAGE_SIZE; 
if(END_PAGE>NUM_PAGE-1) 
{ 
//not enough memory 
return; 
} 
PAGE=ADDR/PAGE_SIZE; 
NBYTES[0]=(PAGE+1)*PAGE_SIZE-ADDR; 
NBYTES[1]=(ADDR+N)-(END_PAGE*PAGE_SIZE); 

if(NBYTES[0]) 
{ 
i2c_write_n_bytes(SLA_W,ADDR,NBYTES[0],DAT); 
//delay_ms(10);//模擬時用延時代替器件忙檢測 
while(i2c_check_busy(SLA_W));//器件忙檢測 
} 
if(END_PAGE>PAGE) 
{ 
i=0; 
while(END_PAGE>++PAGE) 
{ 
i2c_write_n_bytes(SLA_W,(PAGE*PAGE_SIZE),PAGE_SIZE,(DAT+NBYTES[0]+(i++)*PAGE_SIZE)); 
//delay_ms(10);//模擬時用延時代替器件忙檢測 
while(i2c_check_busy(SLA_W));//器件忙檢測 
} 
if(NBYTES[1]) 
{ 
i2c_write_n_bytes(SLA_W,(PAGE*PAGE_SIZE),NBYTES[1],(DAT+NBYTES[0]+i*PAGE_SIZE)); 
//delay_ms(10);//模擬時用延時代替器件忙檢測 
while(i2c_check_busy(SLA_W));//器件忙檢測 
} 
} 
} 

/************************************************************************ 
I2C主機從從器件(EEPROM)讀N位元組資料 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明: 
SLA_R:      從器件讀地址 
PAGE_SIZE: EEPROM頁大小(單位:位元組) 
NUM_PAGE:  EEPROM總頁數 
ADDR:      從器件內部讀資料起始地址 
N:        讀資料位元組數 
DAT:      目標資料起始地址 
************************************************************************/ 
void SEEPROM_read_n_bytes(unsigned char SLA_R,unsigned int PAGE_SIZE,unsigned int NUM_PAGE, 
unsigned int ADDR,unsigned int N,unsigned char *DAT) 
{ 
unsigned int PAGE,END_PAGE,NBYTES[2],i; 
END_PAGE=(ADDR+N)/PAGE_SIZE; 
if(END_PAGE>NUM_PAGE-1) 
{ 
//not enough memory 
return; 
} 
PAGE=ADDR/PAGE_SIZE; 
NBYTES[0]=(PAGE+1)*PAGE_SIZE-ADDR; 
NBYTES[1]=(ADDR+N)-(END_PAGE*PAGE_SIZE); 

if(NBYTES[0]) 
{ 
i2c_read_n_bytes(SLA_R,ADDR,NBYTES[0],DAT); 
} 
if(END_PAGE>PAGE) 
{ 
i=0; 
while(END_PAGE>++PAGE) 
{ 
i2c_read_n_bytes(SLA_R,(PAGE*PAGE_SIZE),PAGE_SIZE,(DAT+NBYTES[0]+(i++)*PAGE_SIZE)); 
} 
if(NBYTES[1]) 
{ 
i2c_read_n_bytes(SLA_R,(PAGE*PAGE_SIZE),NBYTES[1],(DAT+NBYTES[0]+i*PAGE_SIZE)); 
} 
} 
} 

//PCF8563時鐘停止指令 
void PCF8563_stop(void) 
{ 
unsigned char stopcode=0x20; 
i2c_write_n_bytes(SLA_W_PCF8563,0,1,&stopcode); 
} 

//PCF8563時鐘啟動指令 
void PCF8563_start(void) 
{ 
unsigned char startcode=0x00; 
i2c_write_n_bytes(SLA_W_PCF8563,0,1,&startcode); 
} 

/************************************************************************ 
PCF8563時鐘設定 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明:(BCD碼) 
yy: 年(0x00到0x99) 
mm: 月(0x01到0x12) 
dd: 日(0x01到0x31) 
hh: 時(0x00到0x23) 
mi: 分(0x00到0x59) 
ss: 秒(0x00到0x59) 
da: 星期(0x01到0x07) 
************************************************************************/ 
void PCF8563_set(unsigned char yy,unsigned char mm,unsigned char dd, 
unsigned char da,unsigned char hh,unsigned char mi,unsigned char ss) 
{ 
unsigned char time[7]; 
time[6]=yy;  //年 
time[5]=mm;//月 
time[4]=da; //星期 
time[3]=dd; //日 
time[2]=hh;//時 
time[1]=mi;//分 
time[0]=ss;//秒 
PCF8563_stop(); 
i2c_write_n_bytes(SLA_W_PCF8563,2,7,time); 
PCF8563_start(); 
} 

/************************************************************************ 
PCF8563時鐘讀取 
程式設計:許工 QQ11520389 
時間:2010.03.05 
引數說明:(BCD碼) 
time: 存放讀出時間的陣列名 
time[6]: 年(0x00到0x99) 
time[5]: 月(0x01到0x12) 
time[3]: 日(0x01到0x31) 
time[2]: 時(0x00到0x23) 
time[1]: 分(0x00到0x59) 
time[0]: 秒(0x00到0x59) 
time[4]: 星期(0x01到0x07) 
************************************************************************/ 
void PCF8563_read(unsigned char *time) 
{ 
i2c_read_n_bytes(SLA_R_PCF8563,2,7,time); 
//time[6] //年 
time[5] &= 0x1F;//月 
time[4] &= 0x07;//星期 
time[3] &= 0x3F;//日 
time[2] &= 0x3F;//時 
time[1] &= 0x7F;//分 
time[0] &= 0x7F;//秒 
} 


void main(void) 
{ 
unsigned char dat[132]; 
unsigned int i; 

DDRD|=3;//RED ON 
PORTD|=1; 

DDRC&=~(BIT(PC4)|BIT(PC5));//Pull up the pin SDA and SCL 
PORTC|=BIT(PC4)|BIT(PC5); 

TWCR=0; 
TWBR=12; //set bit rate 
TWSR=0; //set prescale 
/* 
PCF8563_set(0x10,0x03,0x04,0x04,0x11,0x25,0x45); 
delay_ms(1000); 
PCF8563_read(dat); 
//*/ 
//* 
for(i=0;i<132;i++) dat=i; 
for(i=0;i<2;i++) 
SEEPROM_write_n_bytes(SLA_W_24C64,PAGE_SIZE_24C64,NUM_PAGE_24C64,i*66+4,66,dat); 
//*/ 
//* 
for(i=0;i<132;i++) dat=255; 
SEEPROM_read_n_bytes(SLA_R_24C64,PAGE_SIZE_24C64,NUM_PAGE_24C64,4,132,dat); 
//*/ 
EEPROM_WRITE(0, dat); 

PORTD&=~1; 
PORTD|=2;//GREEN ON 
} 

相關推薦

硬體I2CTWIPCF856324CXX程式

//ICC-AVR application builder : 2010-3-5 13:51:50 // Target : M88 // Crystal: 8.0000Mhz #include <iom88v.h> #include <macro

CYQ.DataV5分離使用方法 (如何配置與對應的效果)

nbsp bsp add sla 表現 sys catch 配置 exception 之前寫過一篇關於CYQ.Data 關於讀寫分離的使用心得。但在測試時,出現過各種的意外表現,未能達到預期效果。然後經過"路過秋天"這幾天的調優以後。各種使用環境均已達到預期效果。 今天在這

字符

target null feo uva tchar spa ret ufs 一個 UVa 272,Tex Quotes: 輸入一段話,將引號由" ‘‘換成`` ‘‘輸出。 fgetc(fin); getchar(); fgets(buf,maxn,fin); 從打開

NOIP複賽複習外掛與高精度模板

讀入輸出掛 讀入輸出掛就是逐個字元地讀入資料,從而讓讀入更加快速。輸出掛的原理也是一樣的,都是通過將輸出數字變成輸出字元以加快速度。當然輸入輸出外掛一般用在大量輸入輸出的情況下,這樣價效比才高一些,否則得不償失。 void Rd(int &res){  &nbs

Java併發8- 鎖中的效能之王:StampedLock

在上一篇《你真的懂ReentrantReadWriteLock嗎?》中我給大家留了一個引子,一個更高效同時可以避免寫飢餓的讀寫鎖---StampedLock。StampedLock實現了不僅多個讀不互相阻塞,同時在讀操作時不會阻塞寫操作。 為什麼StampedLock這麼神奇?能夠達到這種效果,它的核心思想在

Java併發——鎖框架

1. 讀寫鎖機制——ReadWriteLock介面 讀寫鎖適用於對資料結構頻繁讀而較少修改的場景。舉個栗子,你可以建立一個線上詞典供多條讀執行緒併發讀取,然而單條寫執行緒可能會不時新增新的定義或更新已有的定義。一個資源可以被多個執行緒同時讀,或者被一個執行緒寫,但是不能同時存在讀和寫執行緒。&n

python資料儲存系列教程——pythonpandascsv檔案

全棧工程師開發手冊 (作者:欒鵬) CSV檔案的規範 1、使用回車換行(兩個字元)作為行分隔符,最後一行資料可以沒有這兩個字元。 2、標題行是否需要,要雙方顯示約定 3、每行記錄的欄位數要相同,使用逗號分隔。逗號是預設使用的值

Java多執行緒程式設計-15-鎖ReentrantReadWriteLock深入分析

上兩篇: 一、前言 上兩篇的內容中已經介紹到了鎖的實現主要有ReentrantLock和ReentrantReadWriteLock。 ReentrantLock是重入鎖,顧名思義就是支援重進入的鎖,他表示該鎖能夠支援一個執行緒對資源的重複加鎖

mysql分離--- 分離實現

現在的mysql讀寫分離方案有很多,在這裡筆者列舉出幾種自己使用過的方案: 1.spring實現route不同的資料來源,來達到讀寫分離的目的。    主要原理是根據service或者dao方法做切面,然後根據規範方法名字首來切換不同的資料來源,實現讀寫分離,好處,速度

Redis教程- 分離

場景 我們為了適應大流量訪問,提高Redis讀寫效率,不能讓訪問洪峰到來時將讀壓力放在一臺伺服器上。所以我們需要提供讀寫分離。由一臺Master伺服器進行寫,同時提供讀的能力。再按需規劃N臺Slave從伺服器提供只讀能力,Master伺服器一旦有寫、更新、

EF通用數據層封裝類支持分離,一主多從

dto cte 功能 pes getc mes 工廠 好的 靈活 淺談orm 記得四年前在學校第一次接觸到 Ling to Sql,那時候瞬間發現不用手寫sql語句是多麽的方便,後面慢慢的接觸了許多orm框架,像 EF,Dapper,Hibernate,ServiceSta

課堂測試四文件

upd select tag art main cor color -s ioe 學生信息管理系統 (本程序以文本方式存儲數據,不通過數組,直接對文件進行操作) 學生類 Student.java 1 public class Student { 2 priva

Python3基礎之十 五檔案1

一、\n 換行命令 定義 text 為字串, 並檢視使用 \n 和不適用 \n 的區別: >>> text='this is first line,this is second line,this is third line' >>> prin

Python3基礎之十 七檔案3

一、讀取檔案內容 file.read() 上一節我們講了,寫檔案用的是'w'和'a',那麼今天來看看讀取檔案怎麼做 使用 file.read() 能夠讀取到文字的所有內容. if __name__=='__main__': file=open('my file.txt',

Python3基礎之十 六檔案2

我們先儲存一個已經有3行文字的 “my file.txt” 檔案, 檔案的內容如下: This is my first test. This is the second line. This the third 然後使用新增文字的方式給這個檔案新增一行 “This is ap

java指定編碼的按行txt檔案幾種方式的比較

輸入輸出的幾種形式 1.FileReader,FileWriter File r = new File("temp.txt") FileReader f = new FileReader(name);//讀取檔案name BufferedReader b = new Buf

深入Mysql鎖機制

深入Mysql鎖機制(二)讀鎖和寫鎖 這篇文章主要來介紹一下MySQL資料庫中的表級鎖。 本文提到的讀鎖和寫鎖都是MySQL資料庫的MyISAM引擎支援的表鎖的。而對於行級鎖的共享讀鎖和互斥寫鎖請閱讀MySQL中的共享鎖與排他鎖。我習慣在描述表鎖的時候按照讀寫來區分,在表

【人生苦短,我用python!】幾行python處理檔案裡面的重複內容包括了檔案,過濾重複!

The beauty of python 1 https://blog.csdn.net/dengyaolongacmblog/article/details/38016905 置頂 2014年07月21日 15:28:18 yaolongdeng 閱讀數:2189 標籤:

java輸入輸出14:IO流位元組流中文

位元組流讀取中文的問題 位元組流在讀中文的時候有可能會讀到半個中文,造成亂碼。 位元組流寫出中文的問題 位元組流直接操作位元組,所以寫出中文必須將字串轉換成位元組陣列。寫出回車換行write("\r\n

shp系列——利用C++進行shp檔案的開啟建立開言

部落格背景和目的 最近在用C++寫一個底層的東西,需要讀取和建立shp檔案。雖然接觸shp檔案已經幾年了,但是對於shp檔案內到底包含什麼東西一直是一知半解。以前使用shp檔案都是利用軟體(如ArcGIS)直接開啟,儲存;建立檔案則需要專門利用ArcToolBox等建立圖形。  網