?? e2prom.c
字號:
//--------------------------------------------------------------------
//
// Copyright 2001 Cygnal Integrated Products, Inc.
//
// 文件名 : 24LC256.c
// 目標器件 : C8051F020
// 編寫日期 : 11/07/05
// 作者 : WuShufeng
//
//
// C8051F0xx通過SMBus與一個EEPROM接口的代碼
// 該程序有兩個具有16位地址空間的EEPROM連在SCL和SDA線上
// 被配置為具有如下從地址
// CHIP_A = 10100000(24LC256)
//
//
//
// 從狀態和競爭狀態沒有定義假設CF020為系統中唯一的主器件
// 功能SM_Send執行向指定EEPROM的單字節寫操作
// SM_Receive執行從指定EEPROM地址讀一個字節的操作兩者都用到存儲器地址
//
// 包含測試代碼部分
//--------------------------------------------------------------------
// 包含文件
//--------------------------------------------------------------------
#include <c8051F020.h>
#include <stdio.h>
#include "Head.h"
//--------------------------------------------------------------------
// 全局常量
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//全局變量
//--------------------------------------------------------------------
char xdata COMMAND; // 在SMBus中斷服務程序中用于保存從地址 + R/W 位
unsigned char xdata WORD; // 保持SMBus要發送的數據字節或剛收到的數據
char xdata BYTE_NUMBER; // 在中用于檢查發送的是什么數據高地址字節低地址字節或數據字節
unsigned char xdata HIGH_ADD, LOW_ADD; // EEPROM存儲器地址的高低字節
bit SM_BUSY; // 該位在發送或接收開始時被置1
// 操作結束后由中斷服務程序清0
//--------------------------------------------------------------------
// 函數原型
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// 主程序
//--------------------------------------------------------------------
//
// 主程序配置交叉開關和SMBus并測試SMBus與三個EEPROM之間的接口
void SMBus_Init (void)
{
SMB0CN = 0x44; // 允許SMBus在應答周期發送ACK
SMB0CR = -55; // SMBus時鐘頻率 = 100kHz.
EIE1 |= 2; // SMBus中斷允許
EA = 1; // 全局中斷允許
SM_BUSY = 0; // 為第一次傳輸釋放SMBus
}
// SMBus 字節寫函數-----------------------------------------------------
// 向給定存儲器地址寫一個字節
//
// out_byte = 待寫數據
// byte_address = 待寫存儲器地址2字節
// chip_select = 待寫EEPROM芯片的器件地址
void SM_Send (unsigned int byte_address,unsigned char out_byte)
{
while (SM_BUSY); // 等待SMBus空閑
SM_BUSY = 1; // 占用SMBus設置為忙
SMB0CN = 0x44; // SMBus允許應答周期發ACK
BYTE_NUMBER = 2; // 2地址字節
COMMAND = (CHIP_A | WRITE); // 片選 + WRITE
HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8位地址
LOW_ADD = (byte_address & 0x00FF); // 低8位地址
WORD = out_byte; // 待寫數據
STA = 1; // 啟動傳輸過程
}
/////SM_Send_str連續寫入
void SM_Send_str (unsigned int byte_address,unsigned char *out_str,unsigned char n)
{
unsigned char xdata i;
for( i = 0;i < n;i ++)
{
SM_Send(byte_address++,*out_str++);
}
}
// SMBus隨機讀函數-----------------------------------------------------
// 從給定存儲器地址讀一個字節
//
// byte_address = 要讀取的存儲器地址
// chip_select = 待讀EEPROM的器件地址
char SM_Receive (unsigned int byte_address)
{
while (SM_BUSY); // 等待總線空閑
SM_BUSY = 1; //占用SMBus設置為忙
SMB0CN = 0x44; // 允許SMBus應答周期發ACK
BYTE_NUMBER = 2; // 2地址字節
COMMAND = (CHIP_A | READ); // 片選 + READ
HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8位地址
LOW_ADD = (byte_address & 0x00FF); // 低8位地址
STA = 1; // 啟動傳輸過程
while (SM_BUSY); // 等待傳輸結束
return WORD;
}
//////SM_Receive_str連續讀出
void SM_Receive_str (unsigned int byte_address,unsigned char *in_str,unsigned char n)
{
unsigned char xdata i;
for(i = 0;i < n;i ++)
{
*in_str++ = SM_Receive(byte_address++);
}
}
//--------------------------------------------------------------------
// 中斷服務程序
//--------------------------------------------------------------------
// SMBus中斷服務程序
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA)
{ // SMBus狀態碼SMB0STA寄存器
// 主發送器/接收器起始條件已發送
// 在該狀態發送的COMMAND字的R/W位總是為0(W)
// 因為對于讀和寫操作來說都必須先寫存儲器地址
case SMB_START:
SMB0DAT = (COMMAND & 0xFE); // 裝入要訪問的從器件的地址
STA = 0; // 手動清除START位
break;
//主發送器/接收器重復起始條件已發送
// 該狀態只應在讀操作期間出現在存儲器地址已發送并得到確認之后
case SMB_RP_START:
SMB0DAT = COMMAND; // COMMAND中應保持從地址 + R.
STA = 0;
break;
// 主發送器從地址 + WRITE已發送收到ACK
case SMB_MTADDACK:
SMB0DAT = HIGH_ADD; // 裝入待寫存儲器地址的高字節
break;
// 主發送器從地址 + WRITE已發送收到NACK
// 從器件不應答發送STOP + START重試
case SMB_MTADDNACK:
STO = 1;
STA = 1;
break;
// 主發送器數據字節已發送收到ACK
// 該狀態在寫和讀操作中都要用到BYTE_NUMBER看存儲器地址狀態 – 如果
// 只發送了HIGH_ADD則裝入LOW_ADD如果LOW_ADD已發送檢查COMMAND
// 中的R/W 值以決定下一狀態
case SMB_MTDBACK:
switch (BYTE_NUMBER)
{
case 2: // 如果BYTE_NUMBER=2
SMB0DAT = LOW_ADD; // 只發送了HIGH_ADD
BYTE_NUMBER--; // 減1為下一輪作準備
break;
case 1: // 如果BYTE_NUMBER=1LOW_ADD已發送
if (COMMAND & 0x01) // 如果R/W=READ發送重復起始條件
STA = 1;
else{
SMB0DAT = WORD; // 如果R/W=WRITE裝入待寫字節
BYTE_NUMBER--;}
break;
default: // 如果BYTE_NUMBER=0傳輸結束
STO = 1;
SM_BUSY = 0; // 釋放SMBus
}
break;
// 主發送器數據字節已發送收到NACK
// 從器件不應答發送STOP + START重試
case SMB_MTDBNACK:
STO = 1;
STA = 1;
break;
// 主發送器競爭失敗
// 不應出現如果出現重新開始傳輸過程
case SMB_MTARBLOST:
STO = 1;
STA = 1;
break;
// 主接收器從地址 + READ 已發送收到ACK
// 設置為在下一次傳輸后發送NACK因為那將是最后一個字節唯一
case SMB_MRADDACK:
AA = 0; // 在應答周期NACK
break;
// 主接收器從地址 + READ 已發送收到NACK
// 從器件不應答發送重復起始條件重試
case SMB_MRADDNACK:
STA = 1;
break;
// 收到數據字節ACK已發送
// 該狀態不應出現因為AA已在前一狀態被清0如果出現發送停止條件
case SMB_MRDBACK:
STO = 1;
SM_BUSY = 0;
break;
// 收到數據字節NACK已發送
// 讀操作已完成讀數據寄存器后發送停止條件
case SMB_MRDBNACK:
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0; // 釋放SMBus
break;
// 在本應用中所有其它狀態碼沒有意義通信復位
default:
STO = 1; // 通信復位
SM_BUSY = 0;
break;
}
SI=0; // 清除中斷標志
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -