AIP650 I2C通讯

AIP650 I2C通讯

/**
 *  @file aip650.c
 *
 *  @date 2020-5-19
 *
 *  @author aron566
 *
 *  @copyright None
 *
 *  @brief AIP650 I2C通讯
 *
 *  @details None
 *
 *  @version V1.1
 */
#ifdef __cplusplus ///<use C compiler
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "aip650.h"
/** Private typedef ----------------------------------------------------------*/

/** Private macros -----------------------------------------------------------*/

/** Private constants --------------------------------------------------------*/
/** Public variables ---------------------------------------------------------*/
Key_Value_Save_t Key_Value_History = 
{
    .Key_value_ptr = NULL ,
    .write_index = 0,
    .read_index  = 0,
    .left_lenth  = 0
};

uint8_t Key_Value_Arr[KEY_VALUE_BUF_MAX] = {0};
/** Private variables --------------------------------------------------------*/

/** Private function prototypes ----------------------------------------------*/
static void Key_value_circle_init(void);
static int CQ_Putdata(uint8_t data);
static void delay_xus(__IO uint32_t nTime);
static void SDA_Output(void);
static void SDA_Input(void);
static void SCL_Output(void);
static void SCL_Input(void);
static void I2C_Init(void);
static void I2C_Start(void);
static void I2C_Stop(void);
static uint8_t I2C_Wait_Ack(void);
static void I2C_Ack(void);
static void I2C_NAck(void);
static void I2C_Send_Byte(uint8_t txd);
static uint8_t I2C_Read_Byte(uint8_t ack);

/** Private user code --------------------------------------------------------*/

/** Private application code -------------------------------------------------*/
/*******************************************************************************
*
*       Static code
*
********************************************************************************
*/
/**
	******************************************************************
	* @brief   模拟I2C us级延时
	* @param   [in]nTime 延时us数
	* @retval  None
	* @author  aron566
	* @version V1.0
	* @date    2020-5-18
	******************************************************************
	*/
static void delay_xus(__IO uint32_t nTime)
{
    int old_val,new_val,val;
 
    if(nTime > 900)
    {
        for(old_val = 0; old_val < nTime/900; old_val++)
        {
            delay_xus(900);
        }
        nTime = nTime%900;
    }
 
    old_val = SysTick->VAL;
    new_val = old_val - CPU_FREQUENCY_MHZ*nTime;
    if(new_val >= 0)
    {
        do
        {
            val = SysTick->VAL;
        }
        while((val < old_val)&&(val >= new_val));
    }
    else
    {
        new_val +=CPU_FREQUENCY_MHZ*1000;
        do
        {
            val = SysTick->VAL;
        }
        while((val <= old_val)||(val > new_val));
    }
}
 
 /**
	******************************************************************
	* @brief   模拟I2C 数据脚配置为输出模式
	* @param   [in]None
	* @retval  None
	* @author  aron566
	* @version V1.0
	* @date    2020-5-18
	******************************************************************
	*/
static void SDA_Output(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = MYI2C_SDA_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;/*GD32输出*/
  GPIO_InitStruct.OutMode = GPIO_OTYPE_PP;/*GD32推挽输出*/
	GPIO_InitStruct.Speed =GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(MYI2C_SDA_PORT,&GPIO_InitStruct);
}
 
 /**
	******************************************************************
	* @brief   模拟I2C 数据脚配置为输入模式
	* @param   [in]None
	* @retval  None
	* @author  aron566
	* @version V1.0
	* @date    2020-5-18
	******************************************************************
	*/
static void SDA_Input(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = MYI2C_SDA_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;/*没有上下拉*/
	GPIO_InitStruct.Speed =GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(MYI2C_SDA_PORT,&GPIO_InitStruct);
}
 
 /**
	******************************************************************
	* @brief   模拟I2C 时钟脚配置为输出模式
	* @param   [in]None
	* @retval  None
	* @author  aron566
	* @version V1.0
	* @date    2020-5-18
	******************************************************************
	*/
static void SCL_Output(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = MYI2C_SCL_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;/*GD32输出*/
    GPIO_InitStruct.OutMode = GPIO_OTYPE_PP;/*GD32推挽输出*/
	GPIO_InitStruct.Speed =GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(MYI2C_SCL_PORT,&GPIO_InitStruct);
}
 
 /**
	******************************************************************
	* @brief   模拟I2C 时钟脚配置为输入模式
	* @param   [in]None
	* @retval  None
	* @author  aron566
	* @version V1.0
	* @date    2020-5-18
	******************************************************************
	*/
static void SCL_Input(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = MYI2C_SCL_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;/*没有上下拉*/
	GPIO_InitStruct.Speed =GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(MYI2C_SCL_PORT,&GPIO_InitStruct);
}
 
/**
  ******************************************************************
  * @brief   模拟I2C初始化
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_Init(void)
{	
	SCL_Output();
	SDA_Output();
	SCL_Dout_HIGH();
	SDA_Dout_HIGH();
}
 
/**
  ******************************************************************
  * @brief   模拟I2C发出起始信号
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_Start(void)
{
	SDA_Output();
	SDA_Dout_HIGH();
	SCL_Dout_HIGH();
	Delay_us(4);
	SDA_Dout_LOW();
	Delay_us(4);
	SCL_Dout_LOW();
}
 
/**
  ******************************************************************
  * @brief   模拟I2C发出停止信号
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_Stop(void)
{
	SDA_Output();
	SCL_Dout_LOW();
	SDA_Dout_LOW();
	Delay_us(4);
	SCL_Dout_HIGH();
	SDA_Dout_HIGH();
	Delay_us(4);						   	
}
 
/**
  ******************************************************************
  * @brief   模拟I2C等待应答
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static uint8_t I2C_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_Input();
	SDA_Dout_HIGH();Delay_us(1);	   
	SCL_Dout_HIGH();Delay_us(1);	 
	while(SDA_Data_IN())
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			I2C_Stop();
			return 0;
		}
	}
	SCL_Dout_LOW();//时钟输出0 	   
	return 0; 
}
 
/**
  ******************************************************************
  * @brief   模拟I2C应答
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_Ack(void)
{
	SCL_Dout_LOW();
	SDA_Output();
	SDA_Dout_LOW();
	Delay_us(2);
	SCL_Dout_HIGH();
	Delay_us(2);
	SCL_Dout_LOW();
}
 
/**
  ******************************************************************
  * @brief   模拟I2C不应答
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_NAck(void)
{
	SCL_Dout_LOW();
	SDA_Output();
	SDA_Dout_HIGH();
	Delay_us(2);
	SCL_Dout_HIGH();
	Delay_us(2);
	SCL_Dout_LOW();
}					 				     

/**
  ******************************************************************
  * @brief   模拟I2C发送一个字节
  * @param   [in]txd 发送的字节
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void I2C_Send_Byte(uint8_t txd) 
{                        
	uint8_t t;      
	//拉低时钟开始数据传输
	SDA_Output();
	SCL_Dout_LOW();
	for(t=0;t<8;t++)
	{  
		SDA_Write((txd&0x80)>>7);		   
		txd<<=1; 	  
		Delay_us(5);
		SCL_Dout_HIGH();
		Delay_us(5); 	
		SCL_Dout_LOW();
		//Delay_us(2);
  }	 
} 	    

/**
  ******************************************************************
  * @brief   模拟I2C读取一个字节 
  * @param   [in]ack ack=1时,发送ACK,ack=0,发送nACK 
  * @retval  读取到的字节
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static uint8_t I2C_Read_Byte(uint8_t ack)
{
	unsigned char i,receive=0;
	//SDA设置为输入
	SDA_Input();
  for(i=0;i<8;i++ )
	{
		SCL_Dout_LOW();
		Delay_us(5);
		SCL_Dout_HIGH();
		receive<<=1;
		if(SDA_Data_IN())receive++;   
		Delay_us(5); 
  }					 
  if(!ack)I2C_NAck();/**< 发送nACK*/
  else  I2C_Ack(); 	 /**< 发送ACK*/   
  
	return receive;
}

/**
  ******************************************************************
  * @brief   加入数据到环形缓冲区
  * @param   [in]data 一个字节数据
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static int CQ_Putdata(uint8_t data)
{
    if(Key_Value_History.left_lenth < KEY_VALUE_BUF_MAX)
    {
        Key_Value_History.Key_value_ptr[Key_Value_History.write_index] = data;//存入缓存
        Key_Value_History.write_index = (Key_Value_History.write_index + 1) % KEY_VALUE_BUF_MAX;//偏移下次存入地址
        Key_Value_History.left_lenth++;//未读数据++
        return 0;
    }
    return -1;
}
/**
  ******************************************************************
  * @brief   按键键值环形缓冲区初始化
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
static void Key_value_circle_init(void)
{
    Key_Value_History.Key_value_ptr = Key_Value_Arr;
    Key_Value_History.read_index  = 0;
    Key_Value_History.write_index = 0;
}
/** Public application code --------------------------------------------------*/
/*******************************************************************************
*
*       Public code
*
********************************************************************************
*/
/**
  ******************************************************************
  * @brief   初始化AIP650 默认关断所有指示灯
  * @param   [in]None
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
void AIP_650_Init_Opt(void)
{  
    I2C_Init();//i2c初始化
    Key_value_circle_init();//!< 键值缓冲区初始化
    I2C_Start();
    I2C_Send_Byte(0x48);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x00);
    while(I2C_Wait_Ack());
    I2C_Stop();

    I2C_Start();
    I2C_Send_Byte(0x48);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x01);
    while(I2C_Wait_Ack());
    I2C_Stop();

    I2C_Start();
    I2C_Send_Byte(0x68);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x00);
    while(I2C_Wait_Ack());
    I2C_Stop();

    I2C_Start();
    I2C_Send_Byte(0x6A);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x00);
    while(I2C_Wait_Ack());
    I2C_Stop();

    I2C_Start();
    I2C_Send_Byte(0x6C);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x00);
    while(I2C_Wait_Ack());
    I2C_Stop();

    I2C_Start();
    I2C_Send_Byte(0x6E);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(0x00);
    while(I2C_Wait_Ack());
    I2C_Stop();
}

/**
  ******************************************************************
  * @brief   读取AIP650按键键值,并加入到环形缓冲区
  * @param   [in]None
  * @retval  按键键值
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
uint8_t Read_Aip650_Key_Value(void)
{
    static uint8_t ret = 0;
    uint8_t Current_key_act = 0;
    I2C_Start();
    I2C_Send_Byte(0x4F);
    while(I2C_Wait_Ack());
    Current_key_act = I2C_Read_Byte(0);
    I2C_Stop();
    
    switch(Current_key_act)
    {
      case 0x45://S1
      case 0x4D://S2
      case 0x55://S3
      case 0x5D://S4 
      case 0x65://S5
      case 0x6D://S6
      case 0x75://S7
      case 0xFF://S8
      case 0x47://S9
      case 0x4F://S10
      case 0x57://S11
      case 0x5F://S12
        ret = Current_key_act;
        break;
      default :
        if(ret)
        {
            //按键松开,才判定一个按键产生
            CQ_Putdata(ret);
            ret = 0;
        }
        return 0;
    }
    return ret;
}

/**
  ******************************************************************
  * @brief   从环形缓冲区取出数据
  * @param   [in]None
  * @retval  一个字节数据
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
uint8_t CQ_Getdata(void)
{
    uint8_t ret_data = 0;
    if(Key_Value_History.left_lenth > 0)
    {
        ret_data = Key_Value_History.Key_value_ptr[Key_Value_History.read_index];//!< 读取数据
        Key_Value_History.read_index = (Key_Value_History.read_index+1 >= KEY_VALUE_BUF_MAX ? 0 : Key_Value_History.read_index+1);//!< 地址偏移
        Key_Value_History.left_lenth--;//!< 未读数据--
        return ret_data;
    }    
    return 0;
}

/**
  ******************************************************************
  * @brief   设置LED值
  * @param   [in]command 0-7bit 控制HL1-HL8 8-15bit 控制HL9-HL10
  * @retval  None
  * @author  aron566
  * @version V1.0
  * @date    2020-5-18
  ******************************************************************
  */
void Set_LED_ON_OFF(uint32_t command)
{
    I2C_Start();
    I2C_Send_Byte(0x68);
    while(I2C_Wait_Ack());
    I2C_Send_Byte(command&0xFF);    //!< 0-7 控制HL1-HL8
    while(I2C_Wait_Ack());
    I2C_Stop();
    
    I2C_Start();
    I2C_Send_Byte(0x6C);
    while(I2C_Wait_Ack());
    I2C_Send_Byte((command>>8)&0x03);//!< 8-15 控制HL9-HL10
    while(I2C_Wait_Ack());
    I2C_Stop(); 
}
#ifdef __cplusplus ///<end extern c
}
#endif

/**
 *  @file aip650.h
 *
 *  @date 2020-5-19
 *
 *  @author aron566
 *
 *  @brief AIP650 I2C通讯
 *  
 *  @version V1.1
 */
#ifndef __MYI2C_H__
#define __MYI2C_H__
#ifdef __cplusplus ///<use C compiler
extern "C" {
#endif
/** Includes -----------------------------------------------------------------*/
#include <stdint.h> /**< nedd definition of uint8_t */
#include <stddef.h> /**< need definition of NULL    */
//#include <stdbool.h>/**< need definition of BOOL    */
#include <stdio.h>  /**< if need printf             */
#include <stdlib.h>
#include <string.h>
/** Private includes ---------------------------------------------------------*/
#include "main.h"
/** Private defines ----------------------------------------------------------*/
/**
 * @name CPU频率
 * @{
 */
#define CPU_FREQUENCY_MHZ 200
/** @}*/
/**
 * @name 模拟I2C引脚定义,及配置功能
 * @{
 */
#define MYI2C_SCL_PIN	AIP_SCL_Pin
#define MYI2C_SCL_PORT	AIP_SCL_GPIO_Port
#define MYI2C_SDA_PIN	AIP_SDA_Pin
#define MYI2C_SDA_PORT	AIP_SDA_GPIO_Port
/** @}*/
//按键缓存大小
#define KEY_VALUE_BUF_MAX 		5U
/** Exported typedefines -----------------------------------------------------*/
/** 键值环形缓冲区*/
typedef struct Key_Value_Save
{
    uint8_t *Key_value_ptr;
    uint8_t write_index;
    uint8_t read_index;
    uint8_t left_lenth;
}Key_Value_Save_t;
/** Exported constants -------------------------------------------------------*/

/** Exported macros-----------------------------------------------------------*/
#define Delay_us(xx)  delay_xus(xx)

#define SDA_Dout_LOW()          HAL_GPIO_WritePin(MYI2C_SDA_PORT,MYI2C_SDA_PIN,GPIO_PIN_RESET) 
#define SDA_Dout_HIGH()         HAL_GPIO_WritePin(MYI2C_SDA_PORT,MYI2C_SDA_PIN,GPIO_PIN_SET)
#define SDA_Data_IN()           HAL_GPIO_ReadPin(MYI2C_SDA_PORT,MYI2C_SDA_PIN)
#define SCL_Dout_LOW()          HAL_GPIO_WritePin(MYI2C_SCL_PORT,MYI2C_SCL_PIN,GPIO_PIN_RESET) 
#define SCL_Dout_HIGH()         HAL_GPIO_WritePin(MYI2C_SCL_PORT,MYI2C_SCL_PIN,GPIO_PIN_SET)
#define SCL_Data_IN()           HAL_GPIO_ReadPin(MYI2C_SCL_PORT,MYI2C_SCL_PIN)
#define SDA_Write(XX)           HAL_GPIO_WritePin(MYI2C_SDA_PORT,MYI2C_SDA_PIN,(XX?GPIO_PIN_SET:GPIO_PIN_RESET))
/** Exported variables -------------------------------------------------------*/
extern Key_Value_Save_t Key_Value_History;
extern uint8_t Key_Value_Arr[];
/** Exported functions prototypes --------------------------------------------*/

void AIP_650_Init_Opt(void);
uint8_t Read_Aip650_Key_Value(void);
uint8_t CQ_Getdata(void);
void Set_LED_ON_OFF(uint32_t command);

#ifdef __cplusplus ///<end extern c
}
#endif
#endif
/******************************** End of file *********************************/

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
AIP650芯片是一款由无锡中微爱芯推出的带有键盘扫描电路接口的LED驱动控制专用芯片。可以使用KeilC51代码来编写AIP650的驱动程序,只需简单修改GPIO宏定义即可套用程序。该程序可以应用于触摸按键指示灯。 在淘宝上可能没有带有按键检测的AIP650模组,所以有人选择自己画一个块来进行调试验证。 另外,如果你想获取AIP650芯片的详细信息和使用手册,你可以在资源中下载。链接为https://download.csdn.net/download/wanglong3713/40836173。该芯片的驱动程序也可以通用于GN1637和AIP1637等芯片。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [LED驱动,按键扫描芯片AIP650驱动程序](https://download.csdn.net/download/oHuanYing123/12552181)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [[MM32生态]【MM32+模块】系列:07、数码管显示(二)](https://blog.csdn.net/ic2121/article/details/128048124)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [4位数码管显示模块TM1637芯片C语言驱动程序](https://blog.csdn.net/wanglong3713/article/details/121110104)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

aron566

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

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

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

打赏作者

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

抵扣说明:

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

余额充值