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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2753|回復(fù): 1
收起左側(cè)

stm32f407芯片模擬IIC

[復(fù)制鏈接]
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;                                                        // 關(guān)閉系統(tǒng)定時(shí)器
        SysTick->LOAD = nus*(SystemCoreClock/1000000);         // nus *1us延時(shí),這個(gè)計(jì)數(shù)值
        SysTick->VAL = 0;                                                         // 清空標(biāo)志位
        SysTick->CTRL = 5;                                                         // 使能系統(tǒng)定時(shí)器工作,時(shí)鐘源為系統(tǒng)時(shí)鐘168MHz
        while ((SysTick->CTRL & 0x00010000)==0);        // 檢查CTRL寄存器的16bit是否置1,若置1,就代表計(jì)數(shù)完畢
        SysTick->CTRL = 0;                                                         // 關(guān)閉系統(tǒng)定時(shí)器       
}

void delay_ms(uint32_t nms)
{

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

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硬件時(shí)鐘使能
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);       
       
        //串口1硬件時(shí)鐘使能
        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;                        //復(fù)用功能模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點(diǎn):功耗高
        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個(gè)停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;                        //無校驗(yàn)位
        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的硬件時(shí)鐘
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);       


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

}

void sda_pin_mode(GPIOMode_TypeDef pin_mode)
{
        //配置硬件,配置GPIO,端口F,第9個(gè)引腳
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;                        //第9 個(gè)引腳
        GPIO_InitStruct.GPIO_Mode=pin_mode;                //輸出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點(diǎn):功耗高
        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;//總線進(jìn)入忙狀態(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)先傳輸,通過時(shí)序圖觀察到
        for(i=7; i>=0; i--)
        {
                //檢測(cè)對(duì)應(yīng)的bit位是1還是0
                if(byte & (1<<i))
                        SDA_W=1;
                else
                        SDA_W=0;
       
                delay_us(5);
       
                //時(shí)鐘線拉高,數(shù)據(jù)有效
                SCL_W=1;
                delay_us(5);

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


                //時(shí)鐘線拉低,保持占用總線,總線是忙狀態(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í)鐘線拉高,數(shù)據(jù)有效
        SCL_W=1;
        delay_us(5);


        //時(shí)鐘線拉低,數(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í)鐘線拉高,數(shù)據(jù)有效
        SCL_W=1;
        delay_us(5);
       
        //讀取SDA引腳電平
        if(SDA_R)
                ack=1;//無應(yīng)答
        else
                ack=0;//有應(yīng)答

        //時(shí)鐘線拉低,保持占用總線,總線是忙狀態(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ā)送起始信號(hào)
        i2c_start();
       
        //發(fā)送設(shè)備尋址,從機(jī)地址寫訪問地址0xA0
        i2c_send_byte(0xA0);
       
        //等待對(duì)方應(yīng)答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("device address error\r\n");
               
                return -1;
        }


        //發(fā)送訪問數(shù)據(jù)存儲(chǔ)地址
        i2c_send_byte(word_address);
       
        //等待對(duì)方應(yīng)答
        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++);
               
                //等待對(duì)方應(yīng)答
                ack=i2c_wait_ack();
                if(ack)
                {
                        printf("write data error\r\n");
                       
                        return -3;
                }       
       
        }
       
        //結(jié)束通信
        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ā)送起始信號(hào)
        i2c_start();
       
        //發(fā)送設(shè)備尋址,從機(jī)地址寫訪問地址0xA0
        i2c_send_byte(0xA0);
       
        //等待對(duì)方應(yīng)答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("device address with write error\r\n");
               
                return -1;
        }


        //發(fā)送訪問數(shù)據(jù)存儲(chǔ)地址
        i2c_send_byte(word_address);
       
        //等待對(duì)方應(yīng)答
        ack=i2c_wait_ack();
        if(ack)
        {
                printf("word address error\r\n");
               
                return -2;
        }
       
       
        //重新發(fā)送起始信號(hào)
        i2c_start();
       
        //發(fā)送設(shè)備尋址,從機(jī)地址讀訪問地址0xA1
        i2c_send_byte(0xA1);
       
        //等待對(duì)方應(yīng)答
        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();
               
                //主動(dòng)發(fā)應(yīng)答信號(hào)
                i2c_ack(0);
       
       
        }
       
        //讀取最后一個(gè)數(shù)據(jù)
        *p=i2c_recv_byte();       
       
        //主動(dòng)發(fā)無應(yīng)答信號(hào)
        i2c_ack(1);       
       
        //結(jié)束通信
        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的硬件時(shí)鐘,端口F才能工作,說白了就是對(duì)端口F上電
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);       

        //配置硬件,配置GPIO,端口F,第9個(gè)引腳
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;                        //第9 個(gè)引腳
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;                //輸出模式
        GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;                //引腳高速工作,收到指令立即工作;缺點(diǎn):功耗高
        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);
               
                //清空標(biāo)志位
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);       
       
        }
}



評(píng)分

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

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:632424 發(fā)表于 2021-7-29 22:27 | 顯示全部樓層
優(yōu)秀,感謝分享,剛學(xué),我模仿學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 五月天激情婷婷 | 在线视频成人 | 久草精品视频在线看网站免费 | 中文字幕第一区综合 | 欧美精品一区在线观看 | 91在线视频播放 | 天堂中文av| 精品一区二区三区三区 | 亚洲综合视频在线 | 日韩欧美视频在线 | 成年人视频在线播放 | 综合色在线 | 蜜臀久久99精品久久久久久宅男 | 欧美午夜视频 | 91久久久久国产一区二区 | 久久久噜噜噜 | 国产在线免费 | 四虎影院永久免费 | 热久久中文字幕 | 国产91清纯白嫩初高中在线观看 | 久热国产视频 | 91久久国产综合久久 | 黄色三级网 | 精品国产91| 天天插天天狠天天透 | 婷婷色av | 日韩大片在线观看 | 黄色影视 | 国产美女精品视频 | 97超碰人人| 天天做天天爽 | 欧美狠狠干 | 狠狠干免费视频 | 久久私人影院 | 天堂av在线播放 | 欧美综合久久 | 亚洲一区二区在线免费观看 | 日本欧美在线 | 国产精品日韩精品 | 一区二区三区av | 可以在线观看的av |