新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32使用模擬IIC操作EEPROM

STM32使用模擬IIC操作EEPROM

作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
貼出stm32f103vet6使用模擬IIC操作EEPROM的代碼:
頭文件部分i2c.h

#ifndef _i2c_H_
#define _i2c_H_

#include "stm32f10x.h"
#define countof(a) (sizeof(a)/sizeof(*(a)))

#define GPIOA_IDR_Addr (GPIOA_BASE + 8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE + 8) //


/*位帶操作,實現(xiàn)51類似的GPIO控制功能*/
/*IO口操作宏定義 */
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+
0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C

#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //輸出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //輸入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //輸出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //輸入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //輸出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //輸入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //輸出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //輸入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //輸出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //輸入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //輸出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //輸入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //輸出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //輸入

//IO方向設(shè)置
#define SDA_IN() {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=8<<12;}
#define SDA_OUT() {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=3<<12;}

//IO操作函數(shù)
#define IIC_SCL PAout(2) //SCL---PA2
#define IIC_SDA PAout(3) //SDA---PA3
#define READ_SDA PAin(3) //輸入SDA


#define EEPROM_SLAVE_ADDRESS (0x50)

//IIC所有操作函數(shù)
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //發(fā)送IIC開始信號
void IIC_Stop(void); //發(fā)送IIC停止信號
void IIC_Send_Byte(u8 txd); //IIC發(fā)送一個字節(jié)
unsigned char IIC_Read_Byte( void );//IIC讀取一個字節(jié)
u8 IIC_Wait_Ack(void); //IIC等待ACK信號
void IIC_Ack(void); //IIC發(fā)送ACK信號
void IIC_NAck(void); //IIC不發(fā)送ACK信號

unsigned char eeprom_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data);
unsigned char eeprom_read(unsigned char c_slave_address7bit,unsigned char c_reg_address);
unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_read_arr[],unsigned int len);
unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_write_arr[],unsigned int len);
unsigned char read_eeprom_status(unsigned char c_slave_address7bit);



#endif

本文引用地址:http://butianyuan.cn/article/201612/325192.htm
源碼i2c.c

#include "i2c.h"
#include "stm32f10x.h"

static void Delay_us(int value)
{
int i = 0,j;
for(i = 0 ; i < 5 ; i ++)
for(j = 0 ; j < value ; j ++)
;
}

//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Init
// 功能 : 初始化i2c
// 參數(shù) : void
// 作者 : wit_yuan
// 時間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //開漏輸出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_2); //PA2,PA3 輸出高
GPIO_SetBits(GPIOA,GPIO_Pin_3); //PA2,PA3 輸出高
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Start
// 功能 : i2c起始信號
// 參數(shù) : void
// 作者 : wit_yuan
// 時間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
void IIC_Start(void)
{
SDA_OUT(); //由于上一個SCL狀態(tài)是0或者是1,要讓SDA穩(wěn)定輸出,都可以設(shè)置為1。
IIC_SDA=1;
Delay_us(2);

IIC_SCL=1; //讓SCL發(fā)生變化,為0不變,為1則變化,表明數(shù)據(jù)可以變動了。
Delay_us(2);

IIC_SDA=0; //SDA線數(shù)據(jù)變化,從而可以保證發(fā)出的是start信號。
Delay_us(2);

IIC_SCL=0; //將I2C總線鉗住,下一個時間SDA可以輸出高低電平。
Delay_us(4);
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Stop
// 功能 : i2c結(jié)束信號
// 參數(shù) : void
// 作者 : wit_yuan
// 時間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
void IIC_Stop(void)
{
SDA_OUT();
IIC_SDA=0; //上一個狀態(tài)的SCL=0,這個狀態(tài)設(shè)置SDA=0,目的是讓狀態(tài)能反轉(zhuǎn)
Delay_us(2);

IIC_SCL=1; //該時刻設(shè)置SCL=1,然后就可以讓數(shù)據(jù)穩(wěn)定在改狀態(tài)下。
Delay_us(2);

IIC_SDA=1;
Delay_us(4);
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Wait_Ack
// 功能 : 等待i2c的應(yīng)答信號
// 參數(shù) : void
// 作者 : wit_yuan
// 時間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
//等待應(yīng)答信號到來
//返回值:1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
u8 IIC_Wait_Ack(void)
{
u16 ucErrTime=0;

IIC_SCL=0;
Delay_us(1);

SDA_IN(); //SDA設(shè)置為輸入

while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1; //超時,表明數(shù)據(jù)傳輸有問題
}
}
IIC_SCL=1;
Delay_us(1);


IIC_SCL=0;//時鐘輸出0
Delay_us(2);

return 0;
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Ack
// 功能 : 產(chǎn)生i2c的ack應(yīng)答信號
// 參數(shù) : void
// 作者 : wit_yuan
// 時間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
//產(chǎn)生ACK應(yīng)答
void IIC_Ack(void)
{
IIC_SCL=0;
Delay_us(2);

SDA_OUT();
IIC_SDA=0;
Delay_us(1);


IIC_SCL=1;
Delay_us(1);
IIC_SCL=0;
Delay_us(4);

}
//不產(chǎn)生ACK應(yīng)答
void IIC_NAck(void)
{
SDA_OUT();
IIC_SCL=0;
Delay_us(2);

IIC_SDA=1;
Delay_us(2);

IIC_SCL=1;
Delay_us(2);
IIC_SCL=0;
Delay_us(2);
}
//IIC發(fā)送一個字節(jié)
//返回從機有無應(yīng)答
//1,有應(yīng)答
//0,無應(yīng)答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時鐘開始數(shù)據(jù)傳輸
Delay_us(2);
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
Delay_us(2);
IIC_SCL=1;
Delay_us(2);
IIC_SCL=0;
Delay_us(2);
}
}
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
unsigned char IIC_Read_Byte( void )
{
unsigned char i,u_receive=0;
SDA_IN();//SDA設(shè)置為輸入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
Delay_us(4);
IIC_SCL=1;
Delay_us(1);
u_receive<<=1;
if(READ_SDA)
u_receive++;
}

return u_receive;
}



unsigned char eeprom_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data)
{
unsigned char u_wait_err = 0;

IIC_Start();
IIC_Send_Byte(c_slave_address7bit << 1);
u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(c_reg_address);
u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(u_data);
u_wait_err |= IIC_Wait_Ack();

IIC_Stop();

if( u_wait_err == 0)
return 0;
return 1;
}

unsigned char eeprom_read(unsigned char c_slave_address7bit,unsigned char c_reg_address)
{
unsigned char u_temp;
unsigned char u_wait_err = 0;

IIC_Start();
IIC_Send_Byte(c_slave_address7bit << 1);
u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(c_reg_address);
u_wait_err |= IIC_Wait_Ack();

IIC_Start();
IIC_Send_Byte((c_slave_address7bit << 1)+1);
u_wait_err |= IIC_Wait_Ack();

u_temp = IIC_Read_Byte( );
IIC_NAck();//不需要響應(yīng)

IIC_Stop();

return u_temp;
}

unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_read_arr[],unsigned int len)
{
unsigned char u_wait_err = 0;
int i = 0;

IIC_Start();
IIC_Send_Byte(c_slave_address7bit << 1);
u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(c_reg_address);
u_wait_err |= IIC_Wait_Ack();

IIC_Start();
IIC_Send_Byte((c_slave_address7bit << 1)+1);
u_wait_err |= IIC_Wait_Ack();

for(i = 0 ; i < len - 1 ; i ++)
{
c_continue_read_arr[i] = IIC_Read_Byte( );
IIC_Ack();
}

c_continue_read_arr[len-1] = IIC_Read_Byte( );
u_wait_err |= IIC_Wait_Ack();

IIC_Stop();

if(u_wait_err == 0)
return 0;
return 1;
}

//如果數(shù)據(jù)寫入有問題,則返回1,表示錯誤,返回0,表示錯誤
unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
unsigned char c_continue_write_arr[],unsigned int len)
{
unsigned int i;
unsigned int i_err = 0;

IIC_Start();
IIC_Send_Byte(c_slave_address7bit << 1);
i_err |= IIC_Wait_Ack();

IIC_Send_Byte(c_reg_address);
i_err |= IIC_Wait_Ack();

for( i = 0 ; i < len ; i ++ )
{
IIC_Send_Byte(c_continue_write_arr[i]);

i_err |= IIC_Wait_Ack();
}
IIC_Stop();

if(i_err == 0)
return 0;

return 1;
}



//該函數(shù)改寫原來的函數(shù) 2016-09-16 by wit_yuan

unsigned char read_eeprom_status(unsigned char c_slave_address7bit)

{

unsigned int i = 0;

int i_ret = 0;

do

{

IIC_Start();

IIC_Send_Byte(c_slave_address7bit << 1);

i_ret = IIC_Wait_Ack();

i++;

if(i >= 10000)

{

IIC_Stop();

return 1;//表示無響應(yīng)

}

}while(i_ret);

IIC_Stop();

return 0;//表示操作序列結(jié)束

}



主測試程序main.c:

/******************** (C) COPYRIGHT 2015 **************************
* 文件名 :main.c
* 描述 :

**********************************************************************************/
#include "stm32f10x.h"
#include "usart1.h"
#include "i2c.h"


static void delay(int time)
{
int i = 0 ,j = 0;
for(i = 0 ; i < 5 ; i ++)
for(j = 0 ; j < time ; j ++)
;
}

unsigned char g_c_continue_read_array[256];

unsigned char g_c_continue_write[256];

/*
* 函數(shù)名:main
* 描述 :主函數(shù)
* 輸入 :無
* 輸出 :無
*/
int main(void)
{
unsigned int i;
unsigned char value;
/* USART1 config 9600 8-N-1 */
USART1_Config();

printf("--------app run-----------n");

IIC_Init();


//memset(g_c_continue_write,0x32,256);

printf("write:n");
for(i = 0 ; i < 16 ; i ++)
{
//printf("%0x ",g_c_continue_write[i]);
g_c_continue_write[i] = i;
}
printf("n");

eeprom_continue_write(EEPROM_SLAVE_ADDRESS,0,g_c_continue_write,16);


value = read_eeprom_status(EEPROM_SLAVE_ADDRESS);
printf("n status : %dn",value);


//printf("status = %dn",read_eeprom_status());

eeprom_continue_read(EEPROM_SLAVE_ADDRESS,0,g_c_continue_read_array,16);


printf("read:n");
for(i = 0 ; i < 16 ; i ++)
{
printf("%0x ",g_c_continue_read_array[i]);
}
printf("n");


value = eeprom_read(EEPROM_SLAVE_ADDRESS,0x15);
printf("value = 0x%0xn",value);



printf("write:n");
eeprom_write(EEPROM_SLAVE_ADDRESS,0x01,0x25);
value = read_eeprom_status(EEPROM_SLAVE_ADDRESS);
value = eeprom_read(EEPROM_SLAVE_ADDRESS,0x01);
printf("value = 0x%0xn",value);


for(;;)
{

}
}
/******************* (C) COPYRIGHT 2016 *****END OF FILE************/




關(guān)鍵詞: STM32模擬IIC操作EEPRO

評論


技術(shù)專區(qū)

關(guān)閉