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 *********************************/

猜你喜欢

转载自blog.csdn.net/weixin_42892101/article/details/106270487
I2C