STM32使用模擬IIC操作EEPROM
#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) //
/*位帶操作,實(shí)現(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開始信號(hào)
void IIC_Stop(void); //發(fā)送IIC停止信號(hào)
void IIC_Send_Byte(u8 txd); //IIC發(fā)送一個(gè)字節(jié)
unsigned char IIC_Read_Byte( void );//IIC讀取一個(gè)字節(jié)
u8 IIC_Wait_Ack(void); //IIC等待ACK信號(hào)
void IIC_Ack(void); //IIC發(fā)送ACK信號(hào)
void IIC_NAck(void); //IIC不發(fā)送ACK信號(hào)
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
#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
// 時(shí)間 : 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起始信號(hào)
// 參數(shù) : void
// 作者 : wit_yuan
// 時(shí)間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
void IIC_Start(void)
{
SDA_OUT(); //由于上一個(gè)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ù)可以變動(dòng)了。
Delay_us(2);
IIC_SDA=0; //SDA線數(shù)據(jù)變化,從而可以保證發(fā)出的是start信號(hào)。
Delay_us(2);
IIC_SCL=0; //將I2C總線鉗住,下一個(gè)時(shí)間SDA可以輸出高低電平。
Delay_us(4);
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Stop
// 功能 : i2c結(jié)束信號(hào)
// 參數(shù) : void
// 作者 : wit_yuan
// 時(shí)間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
void IIC_Stop(void)
{
SDA_OUT();
IIC_SDA=0; //上一個(gè)狀態(tài)的SCL=0,這個(gè)狀態(tài)設(shè)置SDA=0,目的是讓狀態(tài)能反轉(zhuǎn)
Delay_us(2);
IIC_SCL=1; //該時(shí)刻設(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)答信號(hào)
// 參數(shù) : void
// 作者 : wit_yuan
// 時(shí)間 : 2014-11-07
////////////////////////////////////////////////////////////////////////////
//等待應(yīng)答信號(hào)到來(lái)
//返回值: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í),表明數(shù)據(jù)傳輸有問(wèn)題
}
}
IIC_SCL=1;
Delay_us(1);
IIC_SCL=0;//時(shí)鐘輸出0
Delay_us(2);
return 0;
}
//////////////////////////////////////////////////////////////////////////
// 函數(shù)名 : IIC_Ack
// 功能 : 產(chǎn)生i2c的ack應(yīng)答信號(hào)
// 參數(shù) : void
// 作者 : wit_yuan
// 時(shí)間 : 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ā)送一個(gè)字節(jié)
//返回從機(jī)有無(wú)應(yīng)答
//1,有應(yīng)答
//0,無(wú)應(yīng)答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時(shí)鐘開始數(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個(gè)字節(jié),ack=1時(shí),發(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ù)寫入有問(wèn)題,則返回1,表示錯(cuò)誤,返回0,表示錯(cuò)誤
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ù)改寫原來(lái)的函數(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;//表示無(wú)響應(yīng)
}
}while(i_ret);
IIC_Stop();
return 0;//表示操作序列結(jié)束
}
/******************** (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ù)
* 輸入 :無(wú)
* 輸出 :無(wú)
*/
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************/
評(píng)論