首页 > 其他分享 >DSP学习笔记之IIC

DSP学习笔记之IIC

时间:2024-05-11 14:09:39浏览次数:26  
标签:SCL SETL void 笔记 DSP IIC bit SDA

IIC简介

IIC总线是同步通信的一种特殊形式,是一种串行,半双工的通信,I2C 总线只有两根双向信号线。一根是数据线 SDA,另一根是时钟线 SCL。IIC分为硬件IIC和软件IIC,DSP中有硬件IIC,但是不方便拓展,所以日常使用时使用软件IIC居多。

image-20240511105525534

IIC总线通信过程

  1. 主机发送起始信号启用总线
  2. 主机发送一个字节数据指明从机地址和后续字节的传送方向
  3. 被寻址的从机发送应答信号回应主机
  4. 发送器发送一个字节数据
  5. 接收器发送应答信号回应发送器
  6. …………(循环4.5)
  7. 通信完成后主机发送停止信号释放总线

IIC总线寻址方式

image-20240511104930806

主机在发送起始信号后必须先发送一个字节的数据,该数据的高7位为从机地址,最低位表示后续字节的传送方向,'0'表示主机发送数据,'1'表示主机接收数据;总线上所有的从机接收到该字节数据后都将这7位地址与自己的地址进行比较,如果相同,则认为自己被主机寻址,然后再根据第8位将自己定为发送器或接收器。

起始信号和停止信号

image-20240511105056967
  • SCL为高电平时,SDA由高变低表示起始信号
  • SCL为高电平时,SDA由低变高表示停止信号
  • 起始信号和停止信号都是由主机发出,起始信号产生后总线处于占用状态停止信号产生后总线处于空闲状态

字节传送与应答

image-20240511105214316
  • IIC总线通信时每个字节为8位长度,数据传送时,先传送最高位,后传送低位,发送器发送完一个字节数据后接收器必须发送1位应答位来回应发送器即一帧共有9位

典型IIC时序

  • 主机向从机发送数据
image-20240511130601639
  • 从机向主机发送数据
image-20240511130754979
  • 主机先向从机发送数据,然后从机再向主机发送数据
image-20240511130842925

注:阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送;A表示应答, A非表示非应答,S表示起始信号,P表示终止信号

代码分析

IIC驱动代码

/*******************************************************************************
* 头文件
*******************************************************************************/
#define IIC_SCL_SETH	(GpioDataRegs.GPBSET.bit.GPIO33=1)
#define IIC_SCL_SETL	(GpioDataRegs.GPBCLEAR.bit.GPIO33=1)

#define IIC_SDA_SETH	(GpioDataRegs.GPBSET.bit.GPIO32=1)
#define IIC_SDA_SETL	(GpioDataRegs.GPBCLEAR.bit.GPIO32=1)

#define READ_SDA   		(GpioDataRegs.GPBDAT.bit.GPIO32)


/*******************************************************************************
* 函 数 名         : SDA_OUT
* 函数功能		   : SDA输出配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_OUT(void)
{
	EALLOW;
	GpioCtrlRegs.GPBDIR.bit.GPIO32=1;       //Output. SDA
	EDIS;
}

/*******************************************************************************
* 函 数 名         : SDA_IN
* 函数功能		   : SDA输入配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_IN(void)
{
	EALLOW;
	GpioCtrlRegs.GPBDIR.bit.GPIO32=0;       //Input, SDA
	EDIS;
}

/*******************************************************************************
* 函 数 名         : IIC_Start
* 函数功能		   : 产生IIC起始信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA_SETH;
	IIC_SCL_SETH;
	DELAY_US(5);
	IIC_SDA_SETL;//START:when CLK is high,DATA change form high to low
	DELAY_US(6);
	IIC_SCL_SETL;//钳住I2C总线,准备发送或接收数据
}

/*******************************************************************************
* 函 数 名         : IIC_Stop
* 函数功能		   : 产生IIC停止信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL_SETL;
	IIC_SDA_SETL;//STOP:when CLK is high DATA change form low to high
	IIC_SCL_SETH;
 	DELAY_US(6);
 	IIC_SDA_SETH;//发送I2C总线结束信号
	DELAY_US(6);
}

/*******************************************************************************
* 函 数 名         : IIC_Wait_Ack
* 函数功能		   : 等待应答信号到来
* 输    入         : 无
* 输    出         : 1,接收应答失败
        			 0,接收应答成功
*******************************************************************************/
unsigned char IIC_Wait_Ack(void)
{
	unsigned char tempTime=0;

	IIC_SDA_SETH;
	DELAY_US(1);
	SDA_IN();      //SDA设置为输入
	IIC_SCL_SETH;
	DELAY_US(1);
	while(READ_SDA)
	{
		tempTime++;
		if(tempTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL_SETL;//时钟输出0
	return 0;
}

/*******************************************************************************
* 函 数 名         : IIC_Ack
* 函数功能		   : 产生ACK应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Ack(void)
{
	IIC_SCL_SETL;
	SDA_OUT();
	IIC_SDA_SETL;     //SDA置低电平,表示应答
	DELAY_US(2);
	IIC_SCL_SETH;
	DELAY_US(5);
	IIC_SCL_SETL;
}

/*******************************************************************************
* 函 数 名         : IIC_NAck
* 函数功能		   : 产生NACK非应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_NAck(void)
{
	IIC_SCL_SETL;
	SDA_OUT();
	IIC_SDA_SETH;     //SDA保持高电平,表示非应答
	DELAY_US(2);
	IIC_SCL_SETH;
	DELAY_US(5);
	IIC_SCL_SETL;
}

/*******************************************************************************
* 函 数 名         : IIC_Send_Byte
* 函数功能		   : IIC发送一个字节
* 输    入         : txd:发送一个字节
* 输    出         : 无
*******************************************************************************/
void IIC_Send_Byte(unsigned char txd)
{
	unsigned char t;
	SDA_OUT();
	IIC_SCL_SETL;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
        if((txd&0x80)>0) //0x80  1000 0000
        	IIC_SDA_SETH;
		else
			IIC_SDA_SETL;
        txd<<=1;
        DELAY_US(2);   //对TEA5767这三个延时都是必须的
        IIC_SCL_SETH;
		DELAY_US(2);
		IIC_SCL_SETL;
		DELAY_US(2);
    }
}

/*******************************************************************************
* 函 数 名         : IIC_Read_Byte
* 函数功能		   : IIC读一个字节
* 输    入         : ack=1时,发送ACK,ack=0,发送nACK
* 输    出         : 应答或非应答
*******************************************************************************/
unsigned char IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
    	IIC_SCL_SETL;
    	DELAY_US(2);
        IIC_SCL_SETH;
        receive<<=1;
        if(READ_SDA)receive++;
        DELAY_US(1);
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK
    return receive;
}

初始化代码

IIC的初始化一般是初始化两个GPIO,分别给SCL和SDA使用。

void IICA_Init(void)
{
	EALLOW;
	SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟
	GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;	  	//上拉
	GpioCtrlRegs.GPBDIR.bit.GPIO32 = 1;   	// 输出端口
	GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 0;  	// IO口
	GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; 	// 不同步

	GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;	  	//上拉
	GpioCtrlRegs.GPBDIR.bit.GPIO33 = 1;   	// 输出端口
	GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 0;  	// IO口
	GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;   // 不同步
	EDIS;
}

IIC在AT24C02中的应用

/*******************************************************************************
* 函 数 名         : AT24CXX_ReadOneByte
* 函数功能		   : 在AT24CXX指定地址读出一个数据
* 输    入         : ReadAddr:开始读数的地址
* 输    出         : 读到的数据
*******************************************************************************/
unsigned char AT24CXX_ReadOneByte(Uint16 ReadAddr)
{
	unsigned char temp=0;
    IIC_Start();
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	   //发送写命令
		IIC_Wait_Ack();
		IIC_Send_Byte(ReadAddr>>8);//发送高地址
	}
	else
	{
		IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据
	}
	IIC_Wait_Ack();
    IIC_Send_Byte(ReadAddr%256);   //发送低地址
	IIC_Wait_Ack();
	IIC_Start();
	IIC_Send_Byte(0XA1);           //进入接收模式
	IIC_Wait_Ack();
    temp=IIC_Read_Byte(0);
    IIC_Stop();//产生一个停止条件
	return temp;
}

/*******************************************************************************
* 函 数 名         : AT24CXX_WriteOneByte
* 函数功能		   : 在AT24CXX指定地址写入一个数据
* 输    入         : WriteAddr  :写入数据的目的地址
					 DataToWrite:要写入的数据
* 输    出         : 无
*******************************************************************************/
void AT24CXX_WriteOneByte(Uint16 WriteAddr,unsigned char DataToWrite)
{
    IIC_Start();
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	    //发送写命令
		IIC_Wait_Ack();
		IIC_Send_Byte(WriteAddr>>8);//发送高地址
	}
	else
	{
		IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据
	}
	IIC_Wait_Ack();
    IIC_Send_Byte(WriteAddr%256);   //发送低地址
	IIC_Wait_Ack();
	IIC_Send_Byte(DataToWrite);     //发送字节
	IIC_Wait_Ack();
    IIC_Stop();//产生一个停止条件
	DELAY_US(10*1000);
}

标签:SCL,SETL,void,笔记,DSP,IIC,bit,SDA
From: https://www.cnblogs.com/filosefer/p/18186147

相关文章

  • DSP学习笔记之SPI
    DSP学习笔记之SPISPI介绍SPI的全称是"SerialPeripheralInterface",意为串行外围接口。SPI是一种高速的,全双工,同步的通信总线,SPI采用主从方式工作,一般有一个主设备和一个或多个从设备;SPI需要至少4根线,分别是MISO(主设备输入从设备输出)、MOSI(主设备输出从设备输入)、SCLK(时钟)、C......
  • 软件测评笔记03--软件测试
    软件测试的对象程序、数据、文档 ,跟人没有关系 测试用例要设计有效的功能测试用例,应该做到1、测试用例应该100%地覆盖测试业务需求2、利用场景法模拟核心业务流程的正确执行3、利用场景法设计测试用例时,往往是一个业务流程需要多条验证数据4、利用边界值法设计测试用例,......
  • 第六届·2024 MindSpore 量子计算黑客松热身赛赛题解读
    第六届·2024MindSpore量子计算黑客松火热进行中。本次大赛由量子信息网络产业联盟主办,昇思MindSporeQuantum社区承办,多所高校和单位联合举办。开发者将全面体验全新一代通用量子计算框架MindSporeQuantum。热身赛为量子计算基础学习和编程演练。完成热身赛的前100名选手将有......
  • 【学习笔记】Python 装饰器
    装饰器是Python中一种非常强大的语法特性,它允许你在不改变函数代码的情况下,动态地增加功能。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。下面是Python装饰器的基本语法:defdecorator_function(original_function):defwrapper_function(*args,*......
  • WIN10的BUG:语言栏快捷键重启丢失的问题(解决笔记)
    这个问题据说已存在多年,但一直没有解决:crtl+shift+del导致切换语言的热键丢失-MicrosoftCommunity经过下文的引导,发现真存在这个可能性,参照下文的方法解决W10修改输入法快捷键及快捷键BUG解决-知乎(zhihu.com)在我的电脑中是这样设置的:而这个“美式键盘”的快捷方式每次......
  • 软件测评笔记02--软件工程
     设计模式UML支持13种图,可分为两大类结构图:类图、组合结构图、构件图、部署图、对象图、包图行为图:活动图、交互图(顺序图、通信图、交互概览图、时序图)、用例图、状态图主要作用:数据流图-功能建模实体联系图-数据建模状态迁移图-行为建模开发模型V模型:包括低层测试又......
  • 读书笔记
    《Core.Software.Security.Security.at.the.Source.CN.软件安全.从源头开始》读书笔记概览本书深入探讨了从源头保障软件安全的基本方面,为软件开发生命周期(SDL)中嵌入安全性提供了全面指南。它是开发人员、安全专业人士和软件架构师的重要资源。主要内容概览《软件安全:从源头开......
  • python异常的一些代码笔记
    点击查看代码whileTrue:try:x=int(input("请输入一个数字:"))print("你输入的数字是:",x)except:print("异常,输入的不是数字:")try:a=input("请输入被除数:")b=input("请输入除数:")c=float(a)/float......
  • 软件测评笔记01--网络相关
     IP地址与子网划分主动关闭的Socket端会进入TIME_WAIT状态,一般维持在1-4分钟ESTABLISHED:表示连接已经建立DMZ俗称:隔离区,非军事化区,非安全系统与安全系统之间的缓冲区可以放置一些必须公开的服务器设置,如web服务器、FTP服务器、论坛拒绝服务的实现方式不断发送请求,迫......
  • 204-基于Xilinx Virtex-6 XC6VLX240T 和TI DSP TMS320C6678的信号处理板
    基于XilinxVirtex-6XC6VLX240T和TIDSPTMS320C6678的信号处理板 1、板卡概述    板卡由北京太速科技自主研发,基于VPX架构,主体芯片为两片TIDSPTMS320C6678,两片Virtex-6XC6VLX240T-ff1156FPGA,1个RapidIOSwitch。FPGA连接FMC子卡。FPGA......