TSL2591STM32固件库开发

TSL2591STM32固件库开发

*例程链接*
- 硬件准备:
TSL2591模块
指南者开发板或者其他f103系列板子
杜邦线
- 知识准备:
TSL2591的数据手册
这个是软件翻译版的数据手册,需要结合英文原版看
这个是软件翻译版的数据手册,需要结合英文原版看
STM32F10x中文参考手册在这里插入图片描述

官方资料
TSL25911官方资料

- 编写程序

  1. 这里我们使用了指南者的USART1和I2C1,需要做好初始化
  2. I2C连接:PB7连接SDA ,PB6连接SCL
  3. USART1串口转USB连接电脑

I2C写时序代码在这里插入图片描述

/*-------------------------------------------------*/
/*函数名:TSL2591_Byte_Write                       */
/*参  数:addr 写入寄存器的地址   Data要写入的数据 */
/*返回值:无                                       */
/*功  能:写入一个字节                             */
/*-------------------------------------------------*/
uint32_t TSL2591_Byte_Write(uint8_t addr,uint8_t Data)
{
		I2CTimeout = I2CT_FLAG_TIMEOUT;
	//检测总线是否在忙
	 while(I2C_GetFlagStatus(TSL2591_I2C, I2C_FLAG_BUSY))
   {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
   }
	//发送起始信号
	I2C_GenerateSTART(TSL2591_I2C, ENABLE);
	//检测EV5事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(0);
	}
	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(TSL2591_I2C,TSL2591_ADDRESS,I2C_Direction_Transmitter);
	//检测EV6事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(1);
	
	}
	//检测到EV6事件
	I2C_SendData(TSL2591_I2C,addr|COMMAND_BIT);
	//检测EV8事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR)
	{
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(2);
  } 
	//EV8事件被检测到,发送要存储的数据
	I2C_SendData(TSL2591_I2C,Data);
	//检测EV8_2事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED)==ERROR)
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
  }
		//EV8_2事件被检测到,产生停止信号
	I2C_GenerateSTOP(TSL2591_I2C,ENABLE);
	return 1;
}

I2C读时序代码在这里插入图片描述

/*-------------------------------------------------*/
/*函数名:TSL2591_Byte_Read                        */
/*参  数:addr 读取寄存器的地址   Data要读取的数据 */
/*返回值:无                                       */
/*功  能:读取一个byte的数据                       */
/*-------------------------------------------------*/
uint32_t TSL2591_Byte_Read(uint8_t addr,uint8_t *Data)
{
	 I2CTimeout = I2CT_LONG_TIMEOUT;
	  //检测总线是否在忙
	  while(I2C_GetFlagStatus(TSL2591_I2C, I2C_FLAG_BUSY))
   {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
   }
	//发送起始信号
	I2C_GenerateSTART(TSL2591_I2C, ENABLE);
	//检测EV5事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(10);
	}
	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(TSL2591_I2C,TSL2591_ADDRESS,I2C_Direction_Transmitter);
	//检测EV6事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(11);
	}
	//检测到EV6事件
	I2C_SendData(TSL2591_I2C,addr|COMMAND_BIT);
	//检测EV8事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(12);
	}
	//EV8事件被检测到,产生停止信号
	I2C_GenerateSTOP(TSL2591_I2C,ENABLE);
	
	//第二次产生起始信号
	 I2CTimeout = I2CT_FLAG_TIMEOUT;
	//发送起始信号
	I2C_GenerateSTART(TSL2591_I2C, ENABLE);
	//检测EV5事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(13);
	}
	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(TSL2591_I2C,TSL2591_ADDRESS,I2C_Direction_Receiver);
	//检测EV6事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(14);
	}
	//检测EV7事件
	while(I2C_CheckEvent(TSL2591_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED)==ERROR)
	{
		if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
	}
	//EV7事件被检测到,即数据寄存器有新的有效数据
	*Data=I2C_ReceiveData(TSL2591_I2C);
	//如果是最后一个就不再产生应答
	I2C_AcknowledgeConfig(TSL2591_I2C,DISABLE);
		//通讯完成产生停止讯号
	I2C_GenerateSTOP(TSL2591_I2C,ENABLE);
//	//重新产生应答信号,准备下一次的传输
//	I2C_AcknowledgeConfig(TSL2591_I2C,ENABLE);
	return 1;
}

根据TSL2591数据手册将寄存器宏定义

#ifndef __TSL2591_TEST_H
#define __TSL2591_TEST_H

#include "stm32f10x.h"

//写入和读取寄存器都要用寄存器地址与COMMAND_BIT进行与运算
//例 ENABLE_REGISTER|COMMAND_BIT;
#define COMMAND_BIT           0xA0

//寄存器位写1启用,写0禁用
//Register (0x00)
//使能寄存器
#define ENABLE_REGISTER       0x00
//0位pow
#define ENABLE_POWERON        0x01   //打开电源。该字段激活内部振荡器,以允许定时器和ADC通道工作。
#define ENABLE_POWEROFF       0x00   //关闭电源。
#define ENABLE_AEN            0x02   //ALS使能。此字段激活ALS功能
#define ENABLE_AIEN           0x10   //ALS中断启用。
#define ENABLE_SAI            0x40   //中断后睡眠。断言时,如果产生中断,设备将在ALS循环结束时断电
#define ENABLE_NPIEN          0x80   //无持续中断启用

//控制寄存器 
#define CONTROL_REGISTER      0x01
#define SRESET                0x80    //产生同步复位信号
//AGAIN
#define LOW_AGAIN             0X00//Low gain (1x)   低增益模式
#define MEDIUM_AGAIN          0X10//Medium gain (25x)  中等增益模式
#define HIGH_AGAIN            0X20//High gain (428x)  高增益模式
#define MAX_AGAIN             0x30//Max gain (9876x)  最大增益模式
//ATIME
//ALS时间设置两个光电二极管通道的内部ADC集成时间。
#define ATIME_100MS           0x00//100 millis    最大计数 36863 
#define ATIME_200MS           0x01//200 millis    最大计数 65535 
#define ATIME_300MS           0x02//300 millis    最大计数 65535 
#define ATIME_400MS           0x03//400 millis    最大计数 65535 
#define ATIME_500MS           0x04//500 millis    最大计数 65535 
#define ATIME_600MS           0x05//600 millis    最大计数 65535 

//ALS中断阈值寄存器(0x04-0x0B)
#define AILTL_REGISTER        0x04//ALS低阈值低字节
#define AILTH_REGISTER        0x05//ALS低阈值上限字节
#define AIHTL_REGISTER        0x06//ALS高阈值低字节
#define AIHTH_REGISTER        0x07//ALS高阈值上限字节
#define NPAILTL_REGISTER      0x08//无持续ALS低阈值低字节
#define NPAILTH_REGISTER      0x09//无持续ALS低阈值上限字节
#define NPAIHTL_REGISTER      0x0A//无持续ALS高阈值低字节
#define NPAIHTH_REGISTER      0x0B//无持续ALS高阈值上限字节

//持久化寄存器
#define PERSIST_REGISTER      0x0C
// Bits 3:0
// 0000          Every ALS cycle generates an interrupt     每个ALS周期产生一个中断
// 0001          Any value outside of threshold range       阈值范围之外的任何值
// 0010          2 consecutive values out of range          2个连续值超出范围
// 0011          3 consecutive values out of range          3个连续值超出范围
// 0100          5 consecutive values out of range          5个连续值超出范围
// 0101          10 consecutive values out of range         10个连续值超出范围
// 0110          15 consecutive values out of range         15个连续值超出范围
// 0111          20 consecutive values out of range         20个连续值超出范围
// 1000          25 consecutive values out of range         25个连续值超出范围
// 1001          30 consecutive values out of range         30个连续值超出范围
// 1010          35 consecutive values out of range         35个连续值超出范围
// 1011          40 consecutive values out of range         40个连续值超出范围
// 1100          45 consecutive values out of range         45个连续值超出范围
// 1101          50 consecutive values out of range         50个连续值超出范围
// 1110          55 consecutive values out of range         55个连续值超出范围
// 1111          60 consecutive values out of range         60个连续值超出范围

//ID寄存器      ID寄存器提供设备标识。该寄存器是一个只读寄存器,其值永远不会改变
#define ID_REGISTER           0x12
//状态寄存器    状态寄存器提供设备的内部状态。这个寄存器是只读的 
#define STATUS_REGISTER       0x13//#read only
//ALS数据寄存器    建议按顺序读取所有四个ADC字节
#define CHAN0_LOW             0x14     //ALSCH0数据低字节
#define CHAN0_HIGH            0x15     //ALSCH0数据高位字节
#define CHAN1_LOW             0x16     //ALSCH1数据低字节
#define CHAN1_HIGH            0x14     //ALSCH1数据高位字节

//LUX_DF   GA * 53   GA is the Glass Attenuation factor 
#define LUX_DF                762.0
// LUX_DF                408.0
#define MAX_COUNT_100MS       36863 // 0x8FFF
#define MAX_COUNT             65535 // 0xFFFF

void TSL2591_Enable(void);
void TSL2591_Disable(void);
uint8_t TSL2591_Get_Gain(void);
void TSL2591_Set_Gain(uint8_t Gain);
uint8_t TSL2591_Get_IntegralTime(void);
void TSL2591_Set_IntegralTime(uint8_t Time);

uint8_t TSL2591_Init(void);
uint16_t TSL2591_Read_Lux(void);
void TSL2591_SET_InterruptThreshold(uint16_t SET_LOW, uint16_t SET_HIGH);
void TSL2591_SET_LuxInterrupt(uint16_t SET_LOW, uint16_t SET_HIGH);
uint32_t TSL2591_Read_FullSpectrum(void);
uint16_t TSL2591_Read_Infrared(void);
uint32_t TSL2591_Read_Visible(void);
#endif

编写测试程序程序

/*-------------------------------------------------*/
/*函数名:TSL2591_Read_Lux                         */
/*参  数:无                                       */
/*返回值:返回一个十六位的lux值                    */
/*功  能:读取TSL2591数据以转换为lux   值          */
/*-------------------------------------------------*/
uint16_t TSL2591_Read_Lux(void)
{
    uint16_t atime, max_counts,channel_0,channel_1;
    TSL2591_Enable();
	  //延时
    for(uint8_t i=0; i<TSL2591_Time+2; i++){
        Delay_Ms(100);
    }
		TSL2591_WaitForWriteEnd();
		//检测SDA
    if(GPIO_ReadInputDataBit(I2Cx_SDA_PORT,I2Cx_SDA_PIN) == 1)
            printf("INT 0\r\n"); 
    else
            printf("INT 1\r\n"); 
    channel_0 = TSL2591_Read_Channel0();
    channel_1 = TSL2591_Read_Channel1();
    TSL2591_Disable();
    TSL2591_Enable();
    TSL2591_Byte_Write(0xE7, 0x13);//没有寄存器定义,不知道有什么用,暂且留着
    TSL2591_Disable();
    
    atime = 100 * TSL2591_Time + 100;
    if(TSL2591_Time == ATIME_100MS){
        max_counts = MAX_COUNT_100MS;
    }else{
        max_counts = MAX_COUNT;
    }
    uint8_t gain_t;
    if (channel_0 >= max_counts || channel_1 >= max_counts){
            gain_t = TSL2591_Get_Gain();
            if(gain_t != LOW_AGAIN){
                gain_t = ((gain_t>>4)-1)<<4;
                TSL2591_Set_Gain(gain_t);
                channel_0 = 0;
                channel_1 = 0;
                while(channel_0 <= 0 || channel_1 <=0){
                    channel_0 = TSL2591_Read_Channel0();
                    channel_1 = TSL2591_Read_Channel1();
                }
                    Delay_Ms(100);
            }else{
                printf("Numerical overflow!/r/n");
                return 0;
            }
    }
    double again;
    again = 1.0;
    if(TSL2591_Gain == MEDIUM_AGAIN){
        again = 25.0;
    }else if(TSL2591_Gain == HIGH_AGAIN){
        again = 428.0;
    }else if(TSL2591_Gain == MAX_AGAIN){
        again = 9876.0;
    }
    double Cpl;
    uint16_t lux1,lux2=0;
    
    Cpl = (atime * again) / LUX_DF;
    lux1 = (int)((channel_0 - (2 * channel_1)) / Cpl);
    // lux2 = ((0.6 * channel_0) - (channel_1)) / Cpl;
    // This is a two segment lux equation where the first 
    // segment (Lux1) covers fluorescent and incandescent light 
    // and the second segment (Lux2) covers dimmed incandescent light
		//lux2=((0.6*channel_0)-(channel_1))/Cpl;
		//这是一个两段勒克斯方程,其中
		//第一部分(Lux1)是荧光灯和白炽灯
		//第二部分(Lux2)是暗淡的白炽灯
    if(lux1>lux2){
        return lux1;
    }else{
        return lux2;
    }
}

实验效果
在这里插入图片描述
整个程序的代码比较多,不能完整展示,关键代码在于I2C代码的写时序和读时序需要完整代码可以在顶端连接下载。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大摆钟寄快递

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值