新聞中心

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

        STM32使用模擬IIC操作EEPROM

        作者: 時間:2016-12-03 來源:網絡 收藏
        貼出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) //


        /*位帶操作,實現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方向設置
        #define SDA_IN() {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=8<<12;}
        #define SDA_OUT() {GPIOA->CRL&=0XFFFF0FFF;GPIOA->CRL|=3<<12;}

        //IO操作函數
        #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所有操作函數
        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://www.104case.com/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 ++)
        ;
        }

        //////////////////////////////////////////////////////////////////////////
        // 函數名 : IIC_Init
        // 功能 : 初始化i2c
        // 參數 : 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 輸出高
        }
        //////////////////////////////////////////////////////////////////////////
        // 函數名 : IIC_Start
        // 功能 : i2c起始信號
        // 參數 : void
        // 作者 : wit_yuan
        // 時間 : 2014-11-07
        ////////////////////////////////////////////////////////////////////////////
        void IIC_Start(void)
        {
        SDA_OUT(); //由于上一個SCL狀態(tài)是0或者是1,要讓SDA穩(wěn)定輸出,都可以設置為1。
        IIC_SDA=1;
        Delay_us(2);

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

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

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

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

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

        IIC_SCL=0;
        Delay_us(1);

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

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


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

        return 0;
        }
        //////////////////////////////////////////////////////////////////////////
        // 函數名 : IIC_Ack
        // 功能 : 產生i2c的ack應答信號
        // 參數 : void
        // 作者 : wit_yuan
        // 時間 : 2014-11-07
        ////////////////////////////////////////////////////////////////////////////
        //產生ACK應答
        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);

        }
        //不產生ACK應答
        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é)
        //返回從機有無應答
        //1,有應答
        //0,無應答
        void IIC_Send_Byte(u8 txd)
        {
        u8 t;
        SDA_OUT();
        IIC_SCL=0;//拉低時鐘開始數據傳輸
        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設置為輸入
        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();//不需要響應

        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;
        }

        //如果數據寫入有問題,則返回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;
        }



        //該函數改寫原來的函數 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;//表示無響應

        }

        }while(i_ret);

        IIC_Stop();

        return 0;//表示操作序列結束

        }



        主測試程序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];

        /*
        * 函數名:main
        * 描述 :主函數
        * 輸入 :無
        * 輸出 :無
        */
        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************/




        評論


        技術專區(qū)

        關閉
        主站蜘蛛池模板: 岗巴县| 太仓市| 突泉县| 鹿泉市| 华亭县| 蕉岭县| 漾濞| 古田县| 南宁市| 万全县| 方正县| 樟树市| 湟源县| 乌苏市| 西吉县| 横峰县| 土默特左旗| 曲沃县| 鲁山县| 镇坪县| 维西| 华蓥市| 鄂州市| 且末县| 龙口市| 玉树县| 大安市| 洪江市| 东乡县| 泰宁县| 景德镇市| 黄大仙区| 永城市| 沾益县| 林芝县| 习水县| 托克逊县| 东海县| 高淳县| 溧水县| 临城县|