久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2606|回復: 1
打印 上一主題 下一主題
收起左側

stm32f407芯片模擬IIC

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:954547 發(fā)表于 2021-7-29 17:45 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
#include <stdio.h>
#include "stm32f4xx.h"
#include "sys.h"
#include <string.h>

static GPIO_InitTypeDef                GPIO_InitStruct;
static NVIC_InitTypeDef                NVIC_InitStructure;
static USART_InitTypeDef         USART_InitStructure;

void delay_us(uint32_t nus)
{

        SysTick->CTRL = 0;                                                        // 關閉系統(tǒng)定時器
        SysTick->LOAD = nus*(SystemCoreClock/1000000);         // nus *1us延時,這個計數(shù)值
        SysTick->VAL = 0;                                                         // 清空標志位
        SysTick->CTRL = 5;                                                         // 使能系統(tǒng)定時器工作,時鐘源為系統(tǒng)時鐘168MHz
        while ((SysTick->CTRL & 0x00010000)==0);        // 檢查CTRL寄存器的16bit是否置1,若置1,就代表計數(shù)完畢
        SysTick->CTRL = 0;                                                         // 關閉系統(tǒng)定時器       
}

void delay_ms(uint32_t nms)
{

        while(nms--)
        {
       
                SysTick->CTRL = 0;                                                        // 關閉系統(tǒng)定時器
                SysTick->LOAD = (SystemCoreClock/1000);         // 1ms延時,這個計數(shù)值
                SysTick->VAL = 0;                                                         // 清空標志位
                SysTick->CTRL = 5;                                                         // 使能系統(tǒng)定時器工作,時鐘源為系統(tǒng)時鐘168MHz
                while ((SysTick->CTRL & 0x00010000)==0);        // 檢查CTRL寄存器的16bit是否置1,若置1,就代表計數(shù)完畢
                SysTick->CTRL = 0;                                                         // 關閉系統(tǒng)定時器       
       
        }
}

int fputc(int ch,FILE *file)
{
        USART_SendData(USART1,ch);
        //等待發(fā)送完畢
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);

        return ch;
}

void usart1_init(uint32_t baud)
{

        //端口A硬件時鐘使能
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);       
       
        //串口1硬件時鐘使能
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
       


        //配置硬件,配置GPIO,端口A,第9 10引腳
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;//第9 10引腳
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;                        //復用功能模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點:功耗高
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;                //增加輸出電流的能力
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;                //不需要上下拉電阻
        GPIO_Init(GPIOA,&GPIO_InitStruct);


        //將PA9引腳連接到串口1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);

        //將PA10引腳連接到串口1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);



        USART_InitStructure.USART_BaudRate = baud;                                        //波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;        //8位數(shù)據(jù)位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;                //1個停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;                        //無校驗位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不需要流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //允許串口接收和發(fā)送數(shù)據(jù)
        USART_Init(USART1, &USART_InitStructure);

        //接收數(shù)據(jù)后觸發(fā)中斷
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

        /* 配置串口1 */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        USART_Cmd(USART1, ENABLE);
}

#define SCL_W        PBout(8)
#define SDA_W        PBout(9)
#define SDA_R        PBin(9)

void at24c02_init(void)
{

        //使能端口B的硬件時鐘
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);       


        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9;                        //第 8 9 個引腳
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;                //輸出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點:功耗高
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;                //增加輸出電流的能力
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;                //不需要上下拉電阻
        GPIO_Init(GPIOB,&GPIO_InitStruct);
       
       
        //只要是輸出模式,肯定會有初始電平狀態(tài),看時序圖,空閑狀態(tài)為高電平
        SCL_W=1;
        SDA_W=1;

}

void sda_pin_mode(GPIOMode_TypeDef pin_mode)
{
        //配置硬件,配置GPIO,端口F,第9個引腳
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;                        //第9 個引腳
        GPIO_InitStruct.GPIO_Mode=pin_mode;                //輸出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點:功耗高
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;                //增加輸出電流的能力
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;                //不需要上下拉電阻
        GPIO_Init(GPIOB,&GPIO_InitStruct);


}


void i2c_start(void)
{       
        //保證SDA引腳為輸出模式
        sda_pin_mode(GPIO_Mode_OUT);
       
        SDA_W=1;
        SCL_W=1;
        delay_us(5);
       
        SDA_W=0;
        delay_us(5);
       
        SCL_W=0;//總線進入忙狀態(tài)
        delay_us(5);
}


void i2c_stop(void)
{
        //保證SDA引腳為輸出模式
        sda_pin_mode(GPIO_Mode_OUT);
       
        SDA_W=0;
        SCL_W=1;
        delay_us(5);
       
        SDA_W=1;
        delay_us(5);

}


void i2c_send_byte(uint8_t byte)
{
        int32_t i=0;
       
        //保證SDA引腳為輸出模式
        sda_pin_mode(GPIO_Mode_OUT);

        SDA_W=0;
        SCL_W=0;
        delay_us(5);
       
        //最高有效位優(yōu)先傳輸,通過時序圖觀察到
        for(i=7; i>=0; i--)
        {
                //檢測對應的bit位是1還是0
                if(byte & (1<<i))
                        SDA_W=1;
                else
                        SDA_W=0;
       
                delay_us(5);
       
                //時鐘線拉高,數(shù)據(jù)有效
                SCL_W=1;
                delay_us(5);

       
                //時鐘線拉低,數(shù)據(jù)變更
                SCL_W=0;
                delay_us(5);               
       
        }
}


uint8_t i2c_recv_byte(void)
{
        uint8_t d=0;
        int32_t i;
       
        //保證SDA引腳為輸入模式
        sda_pin_mode(GPIO_Mode_IN);

        for(i=7; i>=0; i--)
        {
                //時鐘線拉高,數(shù)據(jù)有效
                SCL_W=1;
                delay_us(5);
               
                //讀取SDA引腳電平
                if(SDA_R)
                        d|=1<<i;


                //時鐘線拉低,保持占用總線,總線是忙狀態(tài)
                SCL_W=0;
                delay_us(5);       
       
        }

        return d;
}


void i2c_ack(uint8_t ack)
{

        //保證SDA引腳為輸出模式
        sda_pin_mode(GPIO_Mode_OUT);

        SDA_W=0;
        SCL_W=0;
        delay_us(5);
       

        if(ack)
                SDA_W=1;
        else
                SDA_W=0;

        delay_us(5);

        //時鐘線拉高,數(shù)據(jù)有效
        SCL_W=1;
        delay_us(5);


        //時鐘線拉低,數(shù)據(jù)變更
        SCL_W=0;
        delay_us(5);               
}

uint8_t i2c_wait_ack(void)
{
        uint8_t ack=0;
        //保證SDA引腳為輸入模式
        sda_pin_mode(GPIO_Mode_IN);

        //時鐘線拉高,數(shù)據(jù)有效
        SCL_W=1;
        delay_us(5);
       
        //讀取SDA引腳電平
        if(SDA_R)
                ack=1;//無應答
        else
                ack=0;//有應答

        //時鐘線拉低,保持占用總線,總線是忙狀態(tài)
        SCL_W=0;
        delay_us(5);


        return ack;
}


int32_t at24c02_write(uint8_t word_address,uint8_t *data,uint8_t len)
{
        uint8_t ack=0;
       
        uint8_t *p=data;
       
        //發(fā)送起始信號
        i2c_start();
       
        //發(fā)送設備尋址,從機地址寫訪問地址0xA0
        i2c_send_byte(0xA0);
       
        //等待對方應答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("device address error\r\n");
               
                return -1;
        }


        //發(fā)送訪問數(shù)據(jù)存儲地址
        i2c_send_byte(word_address);
       
        //等待對方應答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("word address error\r\n");
               
                return -2;
        }
       
        //連續(xù)寫入數(shù)據(jù)
        while(len--)
        {
                //發(fā)送要寫入的數(shù)據(jù)
                i2c_send_byte(*p++);
               
                //等待對方應答
                ack=i2c_wait_ack();
                if(ack)
                {
                        printf("write data error\r\n");
                       
                        return -3;
                }       
       
        }
       
        //結束通信
        i2c_stop();
       
        printf("write success\r\n");
       
        return 0;

}

int32_t at24c02_read(uint8_t word_address,uint8_t *data,uint8_t len)
{
        uint8_t ack=0;
       
        uint8_t *p=data;
       
        //發(fā)送起始信號
        i2c_start();
       
        //發(fā)送設備尋址,從機地址寫訪問地址0xA0
        i2c_send_byte(0xA0);
       
        //等待對方應答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("device address with write error\r\n");
               
                return -1;
        }


        //發(fā)送訪問數(shù)據(jù)存儲地址
        i2c_send_byte(word_address);
       
        //等待對方應答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("word address error\r\n");
               
                return -2;
        }
       
       
        //重新發(fā)送起始信號
        i2c_start();
       
        //發(fā)送設備尋址,從機地址讀訪問地址0xA1
        i2c_send_byte(0xA1);
       
        //等待對方應答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("device address with read error\r\n");
               
                return -3;
        }       
       
        len=len-1;
       
        //連續(xù)寫入數(shù)據(jù)
        while(len--)
        {
                //讀取數(shù)據(jù)
                *p++=i2c_recv_byte();
               
                //主動發(fā)應答信號
                i2c_ack(0);
       
       
        }
       
        //讀取最后一個數(shù)據(jù)
        *p=i2c_recv_byte();       
       
        //主動發(fā)無應答信號
        i2c_ack(1);       
       
        //結束通信
        i2c_stop();
       
        printf("read success\r\n");
       
        return 0;

}


//主函數(shù)
int main(void)
{
        uint8_t buf[8]={1,2,3,4,5,6,7,8};
        uint32_t i;
       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
       
        //使能端口F的硬件時鐘,端口F才能工作,說白了就是對端口F上電
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);       

        //配置硬件,配置GPIO,端口F,第9個引腳
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;                        //第9 個引腳
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;                //輸出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點:功耗高
        GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;                //增加輸出電流的能力
        GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;                //不需要上下拉電阻
        GPIO_Init(GPIOF,&GPIO_InitStruct);

        //配置串口1波特率為115200bps
        usart1_init(115200);
       
        at24c02_init();
       
        printf("This is at24c02 test\r\n");
       
        printf("at24c02:write addr at 0,data is 1 ~ 8\r\n");
        at24c02_write(0,buf,8);

        delay_ms(10);
        memset(buf,0,sizeof buf);
       
        at24c02_read(0,buf,8);       
        printf("read data is:");
        for(i=0; i<8; i++)
                printf("%02X ",buf[i]);
               
        printf("\r\n");
       
        while(1)
        {

               
        }
}


void USART1_IRQHandler(void)
{
        uint8_t d;
       
        //檢查串口1是否接收到數(shù)據(jù)
        if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
        {
                //讀取數(shù)據(jù)
                d = USART_ReceiveData(USART1);
               
                //清空標志位
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);       
       
        }
}



評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:632424 發(fā)表于 2021-7-29 22:27 | 只看該作者
優(yōu)秀,感謝分享,剛學,我模仿學習
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久小视频 | 久久久夜色精品亚洲 | 亚洲欧洲在线视频 | yiren22 亚洲综合 | 精品一区二区三区四区 | 欧美亚洲第一区 | 国产精品久久一区 | 久久久成人免费视频 | 成人高清网站 | 美国一级片在线观看 | 在线一区视频 | 国产精品一区二区视频 | 欧美日韩高清在线观看 | 国产羞羞视频在线观看 | 欧美黑人一区二区三区 | 人人cao | 99国内精品久久久久久久 | 日韩av一二三区 | 国产亚洲黄色片 | 欧美99| 欧美精品一区三区 | 国产欧美一级二级三级在线视频 | 亚洲欧美国产视频 | 精品欧美乱码久久久久久 | 午夜在线影院 | 日本三级电影在线看 | 国产99在线 | 欧美 | 国产精品美女久久久久久久网站 | 欧美在线视频不卡 | 国产二区在线播放 | 成人午夜免费在线视频 | 无码一区二区三区视频 | 亚洲午夜视频 | 中文字幕一区二区三区日韩精品 | 国产一区二区影院 | 久久久激情 | 一区二区在线免费观看 | 成人午夜精品一区二区三区 | 久久91精品| 岛国二区| 日韩一区在线视频 |