HPTA 32X32d热堆阵列传感器控制流程(二):读EEPROM

       通过上一篇文章我们已经对HPTA 32X32d热堆阵列传感器有了一个比较深入的认识了,接下来我们就可以开始撸码了。

        本次使用的也是STM32F103的demo板,如下图所示,外设必须有一个IIC接口,另外利用现成的USB口作为调试口,工程创建就不再赘述了,MDK工程代码还是使用STM32CubeMX 生成。USB虚拟串口驱动代码之前的文章也写过了,这里也不再重复。

 1、 IIC驱动代码

       看了uutotoyang的文章说使用硬件IIC接口访问HTPA 32X32d有问题,我好奇试了一下,果然有问题,访问EEPROM是正常的,向Sensor发送写控制命令也没问题,主要是向Sensor发送读状态命令失败了,后来还是改为IO模拟IIC,驱动代码如下:

#include "bsp_i2c.h"
#include "main.h"


#define SCL_Pin  GPIO_PIN_8
#define SDA_Pin  GPIO_PIN_9
#define SDA_GPIO_Port  GPIOB
#define SCL_GPIO_Port  GPIOB

void bsp_SDA_IN(void) 	//配置成输入  
{  
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
	GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
} 

void bsp_SDA_OUT(void)//配置成输出
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
	GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}

void bsp_SCK_OUT(void) //配置成输出
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
	GPIO_InitStruct.Pin = SCL_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}

#define bsp_IIC_SCL(x)  do {(x==0) ? (SCL_GPIO_Port->BRR=SCL_Pin) : (SCL_GPIO_Port->BSRR=SCL_Pin);}while(0);
#define bsp_IIC_SDA(x)  do {(x==0) ? (SDA_GPIO_Port->BRR=SDA_Pin) : (SDA_GPIO_Port->BSRR=SDA_Pin);}while(0);

#define bsp_READ_SDA() (SDA_GPIO_Port->IDR & SDA_Pin)


/******************************************************************************
*函  数:void bsp_IIC_Delay(void)
*功 能:IIC延时
*参  数:无
*返回值:无
*备  注: 移植时只需要将bsp_IIC_Delay()换成自己的延时即可
*******************************************************************************/	
void bsp_IIC_Delay(uint8_t us)
{
	for(int i = 0; i < 16; i++)
	{
	    __asm("NOP");//core bus 160M  情况下大概IIC速率 400K
	}
}
/******************************************************************************
*函  数:void IIC_Init(void)
*功 能:IIC初始化
*参  数:无
*返回值:无
*备  注:无
*******************************************************************************/
//#include "string.h"
void bsp_IIC_Init(void)
{			
    bsp_SCK_OUT();
    bsp_SDA_OUT();
    bsp_IIC_SCL(1);
    bsp_IIC_SDA(1);
}
	
void bsp_IIC_Start(void)
{
	bsp_IIC_SCL(0);
	bsp_SDA_OUT(); //sda线输出 
	bsp_IIC_SDA(1);
	bsp_IIC_Delay(4);	
	bsp_IIC_SCL(1);
	bsp_IIC_Delay(4);
 	bsp_IIC_SDA(0); //START:when CLK is high,DATA change form high to low 
	bsp_IIC_Delay(4);
	bsp_IIC_SCL(0); //钳住I2C总线,准备发送或接收数据 
}

	  
void bsp_IIC_Stop(void)
{
	bsp_SDA_OUT(); //sda线输出
	bsp_IIC_SCL(0);
	bsp_IIC_SDA(0); //STOP:when CLK is high DATA change form low to high
	bsp_IIC_Delay(4);
	bsp_IIC_SCL(1); 
	bsp_IIC_Delay(4);
	bsp_IIC_SDA(1); //发送I2C总线结束信号
	bsp_IIC_Delay(4);							   	
}


uint8_t bsp_IIC_WaitAck(void)
{
	uint8_t ucErrTime=0;
	bsp_SDA_IN(); //SDA设置为输入  (从机给一个低电平做为应答) 
	bsp_IIC_SDA(1);bsp_IIC_Delay(1);	   
	bsp_IIC_SCL(1);bsp_IIC_Delay(1);;	 
	while(bsp_READ_SDA())
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			bsp_IIC_Stop();
			return 1;
		}
	}
	bsp_IIC_SCL(0); //时钟输出0 	   
	return 0;  
} 

void bsp_IIC_Ack(void)
{
	bsp_IIC_SCL(0);
	bsp_SDA_OUT();
	bsp_IIC_SDA(0);
	bsp_IIC_Delay(1);
	bsp_IIC_SCL(1);
	bsp_IIC_Delay(2);
	bsp_IIC_SCL(0);
}

void bsp_IIC_NAck(void)
{
	bsp_IIC_SCL(0);
	bsp_SDA_OUT();
	bsp_IIC_SDA(1);
	bsp_IIC_Delay(1);
	bsp_IIC_SCL(1);
	bsp_IIC_Delay(1);
	bsp_IIC_SCL(0);
}					 				     
	  
void bsp_IIC_SendByte(uint8_t data)
{                        
	uint8_t t;   
	bsp_SDA_OUT(); 	    
	bsp_IIC_SCL(0); //拉低时钟开始数据传输
	for(t=0;t<8;t++)
	{              
		bsp_IIC_SDA((data&0x80)>>7);

		bsp_IIC_Delay(1);			
		bsp_IIC_SCL(1);
		data<<=1;

		bsp_IIC_Delay(1);
		bsp_IIC_SCL(0);	 
		__asm("NOP");
		__asm("NOP");
	}
	bsp_IIC_Delay(1);
} 	 
	
uint8_t bsp_IIC_ReadByte(uint8_t ack)
{
	uint8_t i,receive=0;
	bsp_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据
	for(i=0;i<8;i++ )
	{
		bsp_IIC_SCL(0); 
		bsp_IIC_Delay(1);
		bsp_IIC_SCL(1);
		__asm("NOP");
		__asm("NOP");
		receive<<=1;
		if(bsp_READ_SDA())receive++; //从机发送的电平
			bsp_IIC_Delay(1); 
	}					 
	if(ack)
		bsp_IIC_Ack(); //发送ACK 
	else
		bsp_IIC_NAck(); //发送nACK  
	return receive;
}

uint8_t bsp_IIC_ReadByteFromSensor(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf)
{
	bsp_IIC_Start();	
	bsp_IIC_SendByte(I2C_Addr);	 //发送从机地址
	if(bsp_IIC_WaitAck()) //如果从机未应答则数据发送失败
	{
		bsp_IIC_Stop();
		return 1;
	}
	bsp_IIC_SendByte(reg); //发送寄存器地址
	bsp_IIC_WaitAck();	  

	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr+1); //进入接收模式			   
	bsp_IIC_WaitAck();
	*buf=bsp_IIC_ReadByte(0);	   
	bsp_IIC_Stop(); //产生一个停止条件
	return 0;
}

uint8_t bsp_IIC_SendByteToSensor(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{
	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr); //发送从机地址
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop();
		return 1; //从机地址写入失败
	}
	bsp_IIC_SendByte(reg); //发送寄存器地址
	bsp_IIC_WaitAck();	  
	bsp_IIC_SendByte(data); 
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop(); 
		return 1; //数据写入失败
	}
	bsp_IIC_Stop(); //产生一个停止条件

	return 0;
}

uint8_t bsp_IIC_ReadByteFromEEPROM(uint8_t I2C_Addr,uint16_t reg,uint8_t *buf)
{
	bsp_IIC_Start();	
	bsp_IIC_SendByte(I2C_Addr);	 //发送从机地址
	if(bsp_IIC_WaitAck()) //如果从机未应答则数据发送失败
	{
		bsp_IIC_Stop();
		return 1;
	}
	bsp_IIC_SendByte((uint8_t)(reg>>8)); //发送寄存器地址
	bsp_IIC_WaitAck();	  
	bsp_IIC_SendByte((uint8_t)reg); //发送寄存器地址
	bsp_IIC_WaitAck();	
    
	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr+1); //进入接收模式			   
	bsp_IIC_WaitAck();
	*buf=bsp_IIC_ReadByte(0);	   
	bsp_IIC_Stop(); //产生一个停止条件
	return 0;
}

uint8_t bsp_IIC_ReadBytesFromEEPROM(uint8_t I2C_Addr, uint16_t reg, uint8_t *buf, uint16_t len)
{
    uint16_t i = 0; 
    
	bsp_IIC_Start();	
	bsp_IIC_SendByte(I2C_Addr);	 //发送从机地址
	if(bsp_IIC_WaitAck()) //如果从机未应答则数据发送失败
	{
		bsp_IIC_Stop();
		return 1;
	}
	bsp_IIC_SendByte((uint8_t)(reg>>8)); //发送寄存器地址
	bsp_IIC_WaitAck();	  
	bsp_IIC_SendByte((uint8_t)reg); //发送寄存器地址
	bsp_IIC_WaitAck();	  

	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr+1); //进入接收模式			   
	bsp_IIC_WaitAck();
    for(i=0; i<len-1; i++)
    {
        buf[i] = bsp_IIC_ReadByte(1);
    }
    buf[i] = bsp_IIC_ReadByte(0);
	bsp_IIC_Stop(); //产生一个停止条件
	return 0;
}

uint8_t bsp_IIC_SendByteToEEPROM(uint8_t I2C_Addr,uint16_t reg,uint8_t data)
{
	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr); //发送从机地址
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop();
		return 1; //从机地址写入失败
	}
	bsp_IIC_SendByte((uint8_t)(reg>>8)); //发送寄存器地址
	bsp_IIC_WaitAck();	  
	bsp_IIC_SendByte((uint8_t)reg); //发送寄存器地址
	bsp_IIC_WaitAck();	  
    
	bsp_IIC_SendByte(data); 
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop(); 
		return 1; //数据写入失败
	}
	bsp_IIC_Stop(); //产生一个停止条件

	return 0;
}

uint8_t bsp_IIC_SendBytesToEEPROM(uint8_t I2C_Addr,uint16_t reg, uint8_t *data, uint16_t len)
{
    uint16_t i = 0;
    
	bsp_IIC_Start();
	bsp_IIC_SendByte(I2C_Addr); //发送从机地址
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop();
		return 1; //从机地址写入失败
	}
	bsp_IIC_SendByte((uint8_t)(reg>>8)); //发送寄存器地址
	bsp_IIC_WaitAck();	  
	bsp_IIC_SendByte((uint8_t)reg); //发送寄存器地址
	bsp_IIC_WaitAck();	  
    
    for(i=0; i<len-1; i++)
    {
        bsp_IIC_SendByte(data[i]); 
    }
    bsp_IIC_SendByte(data[i]); 
	if(bsp_IIC_WaitAck())
	{
		bsp_IIC_Stop(); 
		return 1; //数据写入失败
	}
	bsp_IIC_Stop(); //产生一个停止条件

	return 0;
}

2、读EEPROM

        IIC驱动写好以后我们就可以读EEPROM中的参数了,先不要管这些参数怎么用,我们只要把数据读出来,并根据数据手册中规定的EEPROM的数据类型去定义一个结构体类型,再用这个新类型去定义一个变量把EEPROM的数据保存下来备用即可,变量类型和访问EEPROM的相关函数代码如下:

#include "bsp_i2c.h"
#include <stdint.h>
#include <stdio.h>

#define SLAVE_ADDR    (0x50<<1)

SENSOR_PARAM_TYPE g_tEEParam = {0};
#define EEPROM_ADDR_PixCmin        0x0000    // float
#define EEPROM_ADDR_PixCmax        0x0004    // float
#define EEPROM_ADDR_GradScale      0x0008    // u8
#define EEPROM_ADDR_TN             0x000B    // u16
#define EEPROM_ADDR_Epsilon        0x000D    // u8
#define EEPROM_ADDR_MBIT_CALIB     0x001A    // u8
#define EEPROM_ADDR_BIAS_CALIB     0x001B    // u8
#define EEPROM_ADDR_CLK_CALIB      0x001C    // u8
#define EEPROM_ADDR_BPA_CALIB      0x001D    // u8
#de
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值