gec210 i2c程序io模拟方式实现

发布者:小星星龙猫最新更新时间:2022-07-28 来源: csdn关键字:i2c程序  模拟方式 手机看文章 扫描二维码
随时随地手机看文章

开发环境:ubuntu arm-linux-gcc4.4.1


开发板: GEC210开发板


原理图


i2c芯片:FM24CL04


与cpu的连接,GPD1的0,1号引脚。0号引脚对应SDA功能,1号引脚对应SCL引脚


实现:


io方式模拟i2c通信,没有使用i2c控制器


需要使用io引脚输出高低电平模拟i2c信号


或者需要改变为输入模式服务数据




//宏定义


#define GPD1DAT (*(volatile unsigned long*)0xe02000c4)


#define GPD1CON (*(volatile unsigned long*)0xe02000c0)

#define UTXH0   (*(volatile unsigned char*)0xe2900020)

#define UTRSTAT0 (*(volatile unsigned long*)0xe2900010)


//函数声明

void sda_set(unsigned char x);

void scl_set(unsigned char x);

void delay(int n);

void i2c_start(void);

void i2c_stop(void);

void sda_input(void);

void sda_output(void);

void scl_output(void);

unsigned char read_sda(void);

unsigned char wait_ack(void);

void send_ack(unsigned char ack);

unsigned char data_read(unsigned char ack_flag);

unsigned char data_write(unsigned char buf);

unsigned char data_write_buf(unsigned short addr,unsigned char*buf,int len);

unsigned char rand_read_buf(unsigned short addr,unsigned char*buf,int len);

void print_hex(int n);

void print_string(char *);


//测试程序

void i2c_main(void)

{

    unsigned char buf[32];

    int i;


    sda_output();

    scl_output();


    print_string("2017nr");

    for(i=0;i<32;i++)

    {

        buf[i] = i + 0x20;

    }

    

    data_write_buf(0x0,buf,30);   //向0地址写入30个值

    

    rand_read_buf(10,buf,20);     //从10地址读取20个值

    

    for(i=0;i<20;i++)

    {

        print_hex(buf[i]);

    }

    print_string("i2c io test overnr");

    return;    

}





//SDA输出高或低电平

//参数 x非0时输出高电平,x为0时输出低电平

void sda_set(unsigned char x)

{

    if(x)

    {    

        GPD1DAT |= 1;    //输出高电平

    }

    else

    {

        GPD1DAT &= ~1;   //输出低电平

    }    

}


//SCL信号输出高电平或低电平

//参数 x非0时输出高电平,x为0时输出低电平

void scl_set(unsigned char x)

{

    if(x)

    {    

        GPD1DAT |= 1<<1;      //输出高电平

    }

    else

    {

        GPD1DAT &= ~(1<<1);    //输出低电平

    }    

}


//延时函数

void delay(int n)

{

    n = 100*n;

    while(n--);     //直到n减为0

}


//i2c的开始时序

//在SCL为高电平时,SDA由高变为低电平

//尽量保证所有的函数进入时SCL为0,函数返回时SCL也为低

void i2c_start(void)

{

    scl_set(0);      //SCL = 0

    sda_set(1);      //SDA = 1

    scl_set(1);      //SCL = 1

    delay(1);

    sda_set(0);   //SDA = 0

    delay(1);

    scl_set(0);      //SCL = 0

}


//i2c的停止时序

//在SCL为高电平时,SDA由低变为高电平

//最后进入空闲状态,SCL和SDA都保持为高电平

void i2c_stop(void)

{

    scl_set(0);      //SCL = 0

    sda_set(0);      //SDA = 0;

    scl_set(1);      //SCL = 1;    

    delay(1);

    sda_set(1);      //SDA = 1

    scl_set(1);      //SCL = 1

}


//SDA切换为输入模式

//在接收数据或接收应答的时候

//SDA为GPD1 io引脚的0号引脚

void sda_input(void)

{

    GPD1CON &= ~0xf;   //输入模式

}



//SDA切换为输入模式

//在发送数据的时候

//SDA为GPD1 io引脚的0号引脚

void sda_output(void)

{

    GPD1CON &= ~0xf;

    GPD1CON |= 1;   //输出模式

}


//SCL作为主机模式的时候,只需要设置为输出模式

//SCL为GPD1 io引脚的1号引脚

void scl_output(void)

{

    GPD1CON &= ~0xf0;

    GPD1CON |= 1<<4;   //输出模式

}


//在输入模式时,读取SDA引脚的信号

//只需要最低位,因为最低位才是SDA引脚的对应信号

unsigned char read_sda(void)

{

    return GPD1DAT & 1;

}



//主机读取从机发回的应答信号

//

unsigned char wait_ack(void)

{    

    unsigned char tmp;

    scl_set(0);      //SCL = 0;

    sda_set(1);   //SDA = 1    ,释放SDA总线

    sda_input();  //SDA切换为输入模式

    delay(1);

    scl_set(1);      //SCL = 1;

    delay(1);

    tmp = read_sda();  //读取SDA信号

    

    scl_set(0);    

    delay(1);

    sda_output();  //SDA切换为输出模式

    return tmp;

}




//主机发送应答信号

//参数ack为0时表示需要应答,为1时不应答

//ack是一个时序过程,就是数据发完的第9位,不管主机要不要发送应答

//这个第9位的时序都要出现在8个数据位之后

void send_ack(unsigned char ack)

{

    scl_set(0);      //SCL = 0;

    delay(1);

    sda_set(ack & 1);   //SDA = 0;

    delay(1);

    scl_set(1);    

    delay(3);

    scl_set(0);

}






//写8bits数据时序

unsigned char data_write(unsigned char buf)

{

    unsigned char i;

    scl_set(0);      //SCL = 0;

    delay(1);

    for(i=0;i<8;i++)

    {

        sda_set((buf>>(7-i)) & 1);

        delay(1);

        scl_set(1);   //SCL = 1;

        delay(5);

        scl_set(0);      //SCL = 0;

        delay(1);

    }

    return wait_ack();  //应答时序

}







//当前地址读操作

//fm24cl04读取数据的操作,当前地址的话,重新上电后的当前地址为0

//所以调试的时候注意以下,尽量断电重启

unsigned char data_read(unsigned char ack_flag)

{

    unsigned char i;

    unsigned char buf = 0;


    scl_set(0);      //SCL = 0;

    sda_input();  //sda输入模式

    delay(1);

    for(i=0;i<8;i++)

    {

        buf<<=1;

        scl_set(1);      //SCL = 1;

        delay(1);

        buf |= read_sda();        

//        delay(1);    

        scl_set(0);      //SCL = 0;    

        delay(1);

    }


    sda_output();  //sda输出模式

    send_ack(ack_flag);   //发送应答

    

    return buf;  //返回收到的数据

}




void i2c_read_buf(unsigned char page,unsigned char*buf,int len)

{

    int i;

    i2c_start();    //起始信号

    while(data_write(0xa1 | (page<<1)) != 0);   //设备地址,读操作,页选择

    

    for(i=0;i    {

        buf[i] = data_read(i==len-1);  //只有i=9才传入1,其他情况为0

    }

    i2c_stop();

    return;    

}





//写操作

//fm24cl04写数据的操作

unsigned char data_write_buf(unsigned short addr,unsigned char*buf,int len)

{

    int i;

    unsigned char page = addr>>8;   //第9位为fm24cl04的页选择

    i2c_start();    //起始信号

    while(data_write(0xa0 | (page << 1)) != 0);   //设备地址,写操作

    

    data_write(addr & 0xff);   //发送空间地址

    

    if(len == 0)   //为随机读创造时序,参看随机读函数

    {

        return;

    }

    

    for(i=0;i    {

        data_write(buf[i]);  //写入数据

    }

    i2c_stop();

}



//随机读函数操作,与当前地址读的差异

//fm24cl04写数据的操作

unsigned char rand_read_buf(unsigned short addr,unsigned char*buf,int len)

{

    data_write_buf(addr,buf,0);

    i2c_read_buf(addr>>8,buf,len);

}





/*******************************************************************************************/

/*

分割线

以下为串口打印函数,不完整。但是使用uboot的换是可以使用的。

暂时不做详细介绍


*/


void uart0_send_byte(unsigned char buf)

{

    while((UTRSTAT0 & (1<<2)) == 0);  //靠靠靠靠靠靠靠靠

    UTXH0 = buf;

}





void print_string(char*str)

{

    while(*str)

    {

        uart0_send_byte(*str++);

    }

}






void print_hex(int n)

{

    unsigned char arr[8];

    unsigned char i;

    unsigned char tmp;


    for(i=0;i<8;i++)

    {

        tmp = n & 0xf;   //靠靠靠靠4靠靠靠?6靠靠靠靠靠靠靠

        if(tmp > 9)

        {

            arr[i] = tmp + 'a' - 10;   //靠靠靠ASCII?

        }

        else

        {

            arr[i] = tmp + '0';

        }

        n >>= 4;

    }

    print_string("0x");


    for(i=0;i<8;i++)

    {

        uart0_send_byte(arr[7-i]);

    }

    print_string("nr");

}

关键字:i2c程序  模拟方式 引用地址:gec210 i2c程序io模拟方式实现

上一篇:GEC210 LED 裸机编程 原理介绍
下一篇:ARM-CP15寄存器组介绍(开启I/D catch,MMU都需要此寄存器)

推荐阅读最新更新时间:2024-11-02 11:20

IO-Link 1.1版本,加速IIoT向高速率时代演进
在工业上,I/O广泛使用了几十年,近年,采用IO-Link的应用急剧增加。此外IEC 61131-9开放标准为自动化部件提供了易于使用的连接。IEC 61131-9 标准(商标名称为 IO-Link )是一种开放标准,它定义了一个使自动化机器中常用的致动器和传感器具有连接功能的系统。据估计,未来数年内支持 IO-Link 功能的设备的销售额每年都会翻倍(截止 2023 年会超过 12 亿美元)。随着越来越多的 OEM 和工厂工程师发现了新购买和现有的硬件具有 IO-Link 功能并加以利用,特别是在过去几年中,IO-Link 的使用急剧增加。 IO-Link是一个单点数字通信接口(SDCI),用于网络小型传感器和执行器,
[工业控制]
<font color='red'>IO</font>-Link 1.1版本,加速IIoT向高速率时代演进
嵌入式系统中闪存设备IO软件的设计与实现
1、引言 随着嵌入式系统应用领域的不断扩大,系统复杂性也在不断提高。闪存作为广泛使用的嵌入式存储设备,其管理技术和访问方式经历了一个由开发员直接控制到由操作系统的 I/O 软件间接控制的过程。然而目前现有的这些闪存管理方案都不能提供一种方便、统一且移植性好的I/O软件接口,增加了嵌入式产品的研发周期。因此,本文旨在针对一般的嵌入式应用,设计并实现一种更合理的闪存I/O软件。该软件遵循策略与机制分离的原则,采用分层的体系结构,能够更好得适应底层硬件的变化,可大大提高代码的可移植性。 2、闪存设备管理技术的现状及存在的问题 闪存设备不同于一般的非易失性存储设备,它有很多特殊的存取特性,其中最主要的在执行写入操作之
[单片机]
嵌入式系统中闪存设备<font color='red'>IO</font>软件的设计与实现
STM8S103 IO口控制
STM8的IO口控制,说好听点是灵活多变,可以各种定制,可是用起来那真是烦,要定义的好多! void io_init() { PA_DDR |= (1 3); PA_CR1 |= (1 3); PA_CR2 &= ~(1 3);//PA3设置为推挽输出 PD_DDR |= (1 5); PD_CR1 |= (1 5); PD_CR2 &= ~(1 5); //PD5设置为推挽输出 PD_DDR &= ~(1 6); //PD6设置为悬浮输入 PD_DDR |= (1 3); PD_CR1 |= (1 3); PD_CR2 &= ~(1
[单片机]
STM32控制IO基本配置的讲解
一个简单的工程搭建好之后,进一步就是了解里面的内容,也就是学习进入正轨。打开我之前新建的工程,主要调用的几个函数就是今天学习的内容,接下来我就讲解一下那些内容。 一、初始化时钟 这里的“时钟配置”函数在bsp.c文件下面; 使能了GPIOA --- GPIOD时钟,这里更加自己使用的IO进行配置(该工程实际只使用GPIOC)。 二、基本输入输出引脚配置 这里的“基本输入输出引脚配置”函数同样在bsp.c文件下面; 初始化GPIO, 包含端口引脚、频率、输出类型。 三、底层初始化 这里的“底层初始化”函数同样在bsp.c文件下面; 以后的底层初始化代码还会增加,这里调用上面的两个函数接口。 四、主函数应用
[单片机]
STM32控制<font color='red'>IO</font>基本配置的讲解
gec210 led裸机开发 汇编指令
软件环境: ADS1.2 硬件平台: GEC210开发板 运行方法:使用uboot下载到内存0x30008000,然后使用go命令运行,查看效果。 该程序的效果,开始为led全部点亮,然后按照二进制加法的变化,直到所有的灯都熄灭,然后又循环。该程序不会再返回到uboot了,是死循环 原理图说明: 4个led通过上拉电阻统一连接到电源正极,led阴极连接到GPJ2io相应的0-3号引脚 所以这4个led都是cpu输出低电平就会点亮,cpu输出高电平led就会熄灭 程序代码如下: AREA init,code,readonly ;设置段属性,代码段,代码段取名inti,只读属性 entry
[单片机]
MSP430F14-直接IO口按键检处理程序
//MSP430F14-直接IO口按键检处理程序 /*************************************************************************/ //分别使用了采个4个按键接到MSP430的通用IO口,按任意一个按键可以使板上的对应LED反转. //例程中,按键采用不断查询方式,以得到键值.并没有使用到低功耗.此程序结构比较适合 //用在非手持设备或非电池供电的设计中.此程序结构比较通用,级用户可参与或套用修改. /*************************************************************************/ #inclu
[单片机]
利用MDK4中的逻辑分析仪分析IO口的PWM波
1、先设置软件仿真 ,可参看STM32不完全手册的2.4的软件仿真这一章 Example functionality: - Clock Settings: - XTAL = 8.00 MHz - SYSCLK = 72.00 MHz - HCLK = SYSCLK = 72.00 MHz - PCLK1 = HCLK/2 = 36.00 MHz - PCLK2 = HCLK = 72.00 MHz - ADCLK = PCLK2/6 = 12.00 MHz - SYSTICK = HCLK/8 = 9.00 MH
[单片机]
利用MDK4中的逻辑分析仪分析<font color='red'>IO</font>口的PWM波
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved