FMD模拟从机IIC,STM模拟主机读取程序

最近打算读一个传感器,时序要求比较严。
批量测试同时读取20个,16ms一组数据,使用一个STM32读取会有影响,就想了一种方法,使用8位机来读取,然后数据转发给STM32。
芯片间采用模拟IIC通讯,并且通讯之前加了一个SDA数据线中断通知(本次是每个8位机单独连接各自的数据线,未使用总线模式,可根据需求改进)。
8位机速度比较慢,处理的比较简单,所以作为从机阻塞等待时钟或数据超时。

整体思路,8位机读取数据,成功后产生一个SDA低电平,等待STM返回SCL低电平后,立即开始等待START信号(8位机反应比较慢,要么增加STM里面的延时,速度会慢;要么等待代码写在同一函数,不要跳转)。
从机读取完一个字节(自定义为读取指令0x44,配置指令0x88,根据需求自己改),返回一个字节0x44或0x88,接着数据校验和,数据高8位,数据低8位。

调试模拟IIC必须的使用示波器,抓到详细的波形,去判断每一步该怎么延时,怎么控制。尤其是起始信号,ASK信号。

8位机使用IO型 FT60F211,引脚定义如下:
增加了模拟串口发送,S1和P1为数据读取引脚。

*                  FT60F211  SOP8 
* // Memory: Flash 1KX14b, EEPROM 128X8b, SRAM 64X8b
*                 ----------------
*  VDD-----------|5(VDD)   (GND)14|-----------GND
*  NC------------|7(PA5)   (PA0)12|------------S1 
*  IICSlaver_SCL-|8(PA4)   (PA1)11|------------P1 
*  IICSlaver_SDA-|9(PA3)   (PA2)10|-------UARTTXD

引脚定义,SDA,SCL在8位机配置为 上拉

#define  IICSlaver_SCL		PA4   
#define  IICSlaver_SDA		PA3

#define SCL_OUT  TRISA4 =0
#define SDA_OUT  TRISA3 =0
#define SDA_IN	 TRISA3 =1

IIC的时序不再多说,主要有下面几种状态:
等待SCL高低电平
等待SDA高低电平
发送高低电平
组成起始信号,停止信号,ASK信号。


//为所使用的硬件平台的寄存器配置   253=1.5ms
#define WAIT_IIC_SCL_HIGH   IICSlaverWaitTimeout = 0;while ( !IICSlaver_SCL )\
		{IICSlaverWaitTimeout++;if(IICSlaverWaitTimeout>253){IICSlaverWaitTimeout = 0;break;}}
#define WAIT_IIC_SCL_LOW    IICSlaverWaitTimeout = 0;while ( IICSlaver_SCL )\
		{IICSlaverWaitTimeout++;if(IICSlaverWaitTimeout>253){IICSlaverWaitTimeout = 0;break;}}
#define WAIT_IIC_SDA_HIGH   IICSlaverWaitTimeout = 0;while ( !IICSlaver_SDA )\
		{IICSlaverWaitTimeout++;if(IICSlaverWaitTimeout>253){IICSlaverWaitTimeout = 0;break;}}
#define WAIT_IIC_SDA_LOW    IICSlaverWaitTimeout = 0;while ( IICSlaver_SDA )\
		{IICSlaverWaitTimeout++;if(IICSlaverWaitTimeout>253){IICSlaverWaitTimeout = 0;break;}}

#define IIC_WAIT_START      WAIT_IIC_SCL_HIGH;WAIT_IIC_SDA_LOW    
#define IIC_WAIT_STOP       WAIT_IIC_SCL_LOW;WAIT_IIC_SCL_HIGH;WAIT_IIC_SDA_HIGH 

#define IIC_SLAVE_SEND_LOW  WAIT_IIC_SCL_LOW; IICSlaver_SDA = 0; SDA_OUT;  \
		WAIT_IIC_SCL_HIGH; WAIT_IIC_SCL_LOW;SDA_IN
#define IIC_SLAVE_SEND_HIGH WAIT_IIC_SCL_LOW; IICSlaver_SDA = 1; SDA_OUT;  \
		WAIT_IIC_SCL_HIGH; WAIT_IIC_SCL_LOW;SDA_IN

#define IIC_SLAVE_SEND_ACK  IIC_SLAVE_SEND_LOW
#define IIC_SLAVE_SEND_NAK  IIC_SLAVE_SEND_HIGH

/*-------------------------------------------------
 *  函数名:IICSlaver_Send_Byte
 *	功能:  IICSlaver发送一个字节
 *  输入:  写入要发送的一个人字节数据txd
 *  输出:  无
 --------------------------------------------------*/		  
void IICSlaver_Send_Byte(uint8_t txd)
{                        
    uint8_t i;   
	for(i = 0; i < 8; i ++)
    {
        WAIT_IIC_SCL_LOW;
        if ( txd & 0x80 )
            IICSlaver_SDA = 1;   
        else    
            IICSlaver_SDA = 0;  
        SDA_OUT;
        txd <<= 1;    
        WAIT_IIC_SCL_HIGH;   
    }
    WAIT_IIC_SCL_LOW;                                               
    SDA_IN;
    WAIT_IIC_SCL_HIGH;
} 	    
/*-------------------------------------------------
 *  函数名:IICSlaver_Read_Byte
 *	功能:  IICSlaver读一个字节
 *  输入:  无
 *  输出:  读出存储器里面的数据并返回receive
 --------------------------------------------------*/
uint8_t IICSlaver_Read_Byte(void)
{
	uint8_t i,receive=0;
	for(i = 0; i < 8; i ++)
	{
		WAIT_IIC_SCL_LOW;                   
		WAIT_IIC_SCL_HIGH;
		receive <<= 1;  //先移位,再读数
		if(IICSlaver_SDA)
			receive |= 0x01;
		else
			receive |= 0x00;
	}
    return receive;
}
 /*-------------------------------------------------
 *  函数名:IICSlaver_WRITE
 *	功能:  发送中断,IICSlaver数据data,sum
 *  输入:  sum,data
 *  输出:  无
 --------------------------------------------------*/
uint8_t IICSlaver_WRITE( uint16_t pirdata)
{
	uint32_t IICSlaverIntTimeout = 0;
	uint8_t datA,datB,sum,reg = 0;
	
	datA=pirdata>>8;
	datB=pirdata;
	sum = datA + datB;
	
	IICSlaver_SDA=0;            //INT
	SDA_OUT;              //SDA线输出

	while(IICSlaver_SCL == 1)
	{
		IICSlaverIntTimeout ++;
		if(IICSlaverIntTimeout > 800)//800=5ms    1000=6.2ms   1500=8.5ms
		{
			IICSlaverIntTimeout = 0;
			SDA_IN;
			// IICSlaver_SDA=1;            //发送I2C总线结束信号	
			return 0;//time out
		}
	}
	SDA_IN;
	// IICSlaver_SDA=1;            //发送I2C总线结束信号	

	IIC_WAIT_START;
	reg = IICSlaver_Read_Byte();
    IIC_SLAVE_SEND_ACK;
	IICSlaver_Send_Byte(0x44);//0x88config  0x44data
	IICSlaver_Send_Byte(sum);
	IICSlaver_Send_Byte(datA);
	IICSlaver_Send_Byte(datB);
    IIC_WAIT_STOP;

	return reg;
}

主函数里面带有一些重新配置跳转的判断

/*-------------------------------------------------
 *  函数名:  main 
 *	功能:  主函数
 *  输入:  无
 *  输出:  无
 --------------------------------------------------*/
void main()
{
	uint8_t modeerr,datA,datB,SUM;
	POWER_INITIAL();				    //系统初始化
    TIMER0_INITIAL();
    DelayMs(200); 
Reconfig:
	while(IICSlaver_ReadMode() == 0)
	{
		DelayMs(10);
	}
	while(1)
	{
        if(GetData)
        {
			GetData = 0;	
			//Send SDA INT , DATA
			modeerr = IICSlaver_WRITE(DataValue&0xffff);
			if((modeerr&0xCC)==0x88)//0x88config  0x44data
			goto Reconfig;		
            
			//UART SEND 9600 7.5ms
			//UART SEND 19200 4ms
			datA=PIRDataValue>>8;
			datB=PIRDataValue;
			SUM=0x47+datA+datB;
			WByte(0xAA);
			WByte(0xAA);
			WByte(0xF1);
			WByte(2);//len
			WByte(datA);
			WByte(datB);
			//			SUM=0xAA+0xAA+0xF1+4+datA+datB+datC+datD;
			WByte(SUM);
        }
	}
}

从机完成。

主机开始,模拟IIC用的就比较多了,基础部分信号产生,应答,发送字节,都是通用的(考虑延时),只需要修改读取函数。
下面是与上面配套的读取流程:



uint8_t ReadDataRegu16(uint16_t *u16dat)
{
	uint8_t reg,sum;
	IIC_Start();
	IIC_Send_Byte(0x44);    //发送地址	 
	if(IIC_Wait_Ack())return 0;
	reg = IIC_Read_Byte(1);//back 0x44	
	if(reg == 0x88)
	{
		IIC_Stop();            //产生一个停止条件	
		return reg;
	}
	sum = IIC_Read_Byte(1);
	*u16dat = IIC_Read_Byte(1);
	*u16dat <<= 8;
	*u16dat |= IIC_Read_Byte(0);	
	IIC_Stop();            //产生一个停止条件	
	
	if(sum == (uint8_t)((*u16dat >> 8) + (*u16dat&0xff)) )
		return reg;
	else 
		return 0;
}

主函数,删了一些无关的,仅供参考

int main(void)
{
	volatile uint8_t reg;
	uint8_t datA,datB,datC,datD,SUM,ADDSUM,Sendcnt;
	uint8_t USARTDMASend;
	uint32_t PIRDataValue;
	LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
 	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
  	SystemClock_Config();
  	MX_GPIO_Init();
//  MX_DMA_Init();
 	MX_USART1_UART_Init();
	
	LL_mDelay(500);
	reconfig:
	SDA_IN();      //SDA设置为输入	8位机上拉,会有SDA中断信号
	Sendcnt = 0;
	while(Sendcnt != 0x88)//Config Mode Reg
	{
		//mode&0xf = 1000 1001 1010 1011
		if(LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5) == 0)//SDAINT
		{
			LL_mDelay(2);//8位机超时前进行下一步

			IIC_SCL=0;//拉低时钟准备读取数据
			delay_xus(5);//减速以防低速读不到信号
			IIC_SCL=1;//准备完成
			
			Sendcnt = SendModeData(0x88|0);//0x88 | 00 MODE
			SDA_IN();      //SDA设置为输入
		}
	}
  while (1)
  {
		if(LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_5) == 0)//SDAINT
		{
			LL_mDelay(2);
			
			IIC_SCL=0;//拉低时钟准备读取数据
			delay_xus(5);//减速以防低速读不到信号
			IIC_SCL=1;//准备完成
			reg = ReadDataRegu16(&Dat.u16PirData);//reg 0x44 data  /  0x88 configmode
			SDA_IN();      //SDA设置为输入	
			if(reg == 0x88)
				goto reconfig;
			else if(reg != 0x44)
				continue;
	
			//发送数据  
			datA=0;//Dat.i16PirData>>24;
			datB=0;//Dat.i16PirData>>16;
			datC=Dat.i16PirData>>8;
			datD=Dat.i16PirData;
	//		DMA1_MEM_LEN = 10;
			USARTDMASEND[0] = 0XAA;
			USARTDMASEND[1] = 0xFF;
			USARTDMASEND[2] = 0xF1;
			USARTDMASEND[3] = 4;
			USARTDMASEND[4] = datD;
			USARTDMASEND[5] = datC;
			USARTDMASEND[6] = datB;
			USARTDMASEND[7] = datA;
			SUM = 0x9E + datD;
			ADDSUM = 0x8B + SUM;
			SUM = SUM + datC;
			ADDSUM = ADDSUM + SUM;
			SUM = SUM + datB;
			ADDSUM = ADDSUM + SUM;
			SUM = SUM + datA;
			ADDSUM = ADDSUM + SUM;
			USARTDMASEND[8] = SUM;
			USARTDMASEND[9] = ADDSUM;
	
			for(Sendcnt = 0;Sendcnt < 10;Sendcnt++)
			USART1SendData(USARTDMASEND[Sendcnt]);
			}
	  }
	while (1);//ERR
}

调试主要还是自己要详细画一画时序,对照示波器来进行调整,例程只是提供一种思路。
有些代码也是仿照其他人,综合起来还需自己调整。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
fmd ide3.1.0是一款功能强大的集成开发环境(IDE),它提供了丰富的工具和功能,旨在帮助开发人员更高效地编写和调试软件。 要下载fmd ide3.1.0,您可以按照以下步骤进行操作: 1. 首先,打开您的网络浏览器(如谷歌浏览器、火狐浏览器等),在搜索引擎中输入"fmd ide3.1.0下载"。 2. 浏览器将会显示搜索结果,您可以点击其中一个可靠的下载链接,例如官方网站或多个软件下载网站,确保该链接来自官方或可信任的源。 3. 一旦您点击了下载链接,您将被导航到fmd ide3.1.0的下载页面。在此页面上,您可能需要选择合适的版本和操作系统,以确保下载的是与您的设备兼容的版本。 4. 点击下载按钮后,浏览器将开始下载fmd ide3.1.0的安装文件。这个过程可能需要一些时间,具体时间取决于您的网络连接速度。 5. 下载完成后,您可以在默认的下载文件夹或您选择的其他文件夹中找到安装文件。通常,这个文件会以一个可执行文件的形式出现。 6. 双击运行安装文件,按照安装提示进行安装。您可能需要选择安装目录和其他一些设置,具体根据安装程序的要求而定。 7. 安装完成后,您将能够在您的计算机上找到并打开fmd ide3.1.0。从此刻起,您可以开始使用该IDE进行软件开发。 总之,fmd ide3.1.0下载过程主要涉及到搜索合适的下载链接,选择合适的版本和操作系统,下载安装文件,然后按照安装提示进行安装。尽管以上是一般的下载步骤,但具体过程可能会因您的设备和网络环境而有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值