/***
Copyright (c) 2016
All rights reserved.
File name :pca9685.c
file identification :
Subject :Say something about the file
Current Version :V1.0.0
Author :Hacker
Date :
Instead Version :
Author :Hacker
Date :
***/
#include "PCA9685.h"
#include "math.h"
#include "delay.h"
#include "Arduino.h"
#include "usart.h"
#define HARDWARE_IIC
#define TEMP37 1365
#define TEMP60 4095
#ifndef HAC_STM32F103C8T6
#define I2C_Channel I2C1
#else
#define I2C_Channel I2C2
#endif
/* STM32 I2C 快速模式 */
#define I2C_Speed 100000
/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */
#define I2C1_OWN_ADDRESS7 0x0A
/* PCA9685写地址 */
#define I2C_Write_ADDRESS 0x80
/* PCA9685读地址 */
#define I2C_Read_ADDRESS 0x81
#define TurnOn() GPIO_ResetBits(GPIOA,GPIO_Pin_5)
#define TurnOff() GPIO_SetBits(GPIOA, GPIO_Pin_5)
static void DELAY_US(u32 n)
{
delay_us(n);
}
/**
* [map description]
* @param x [description]
* @param in_min [description]
* @param in_max [description]
* @param out_min [description]
* @param out_max [description]
* @return [description]
*/
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
/*******************************************************************************
*
* 功能 :I2C I/O配置
* 参数 :无
*
******************************************************************************
*/
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
#ifndef HAC_STM32F103C8T6
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
#else
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
#endif
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
*
* 功能 :I2C 工作模式配置
* 参数 :无
*
******************************************************************************
*/
void I2C_Mode_Configu(void)
{
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 =I2C1_OWN_ADDRESS7;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
I2C_Init(I2C_Channel, &I2C_InitStructure);
I2C_Cmd(I2C_Channel, ENABLE);
}
/*******************************************************************************
*
* 功能 :PCA9685_I2C初始化
* 参数 :无
*
******************************************************************************
*/
u8 I2C_PCA9685_Init(void)
{
u8 data = 0;
#ifdef HARDWARE_IIC
I2C_GPIO_Config();
I2C_Mode_Configu();
#else
IIC_Init();
#endif
data = RESTART_BIT | SLEEP_BIT | ALLCALL_BIT;
if(I2C_ByteWrite(I2C_Write_ADDRESS,PCA9685_MODE1,data))return 1;//0x91 B10010001
DELAY_US(600);
if(I2C_ByteWrite(I2C_Write_ADDRESS,PCA9685_PRESCALE,108))return 1;//108 频率 = 108/2 初始化频率
if(I2C_ByteWrite(I2C_Write_ADDRESS,PCA9685_MODE1,99))return 1;
return 0;
}
/*********************************************************
*
*功能:I2C_ByteWrite
*参数:SlaveAddress:地址;REG_Address:通道;REG_data:数据
*
**********************************************************/
u8 I2C_ByteWrite(u8 SlaveAddress,u8 REG_Address,u16 REG_data)
{
#ifdef HARDWARE_IIC
#define val_time 200
u8 val = val_time;
while(I2C_GetFlagStatus(I2C_Channel, I2C_FLAG_BUSY) && val--)DELAY_US(1);
if(val == 0) return 1;
val = val_time;
I2C_GenerateSTART(I2C_Channel,ENABLE);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_MODE_SELECT) && val--)DELAY_US(1);
if(val == 0) return 1;
val = val_time;
I2C_Send7bitAddress(I2C_Channel,SlaveAddress,I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && val--)DELAY_US(1);
if(val == 0) return 1;
val = val_time;
I2C_SendData(I2C_Channel,REG_Address);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_BYTE_TRANSMITTED) && val--)DELAY_US(1);
if(val == 0) return 1;
val = val_time;
I2C_SendData(I2C_Channel,REG_data);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_BYTE_TRANSMITTED) && val--)DELAY_US(1);
if(val == 0) return 1;
I2C_GenerateSTOP(I2C_Channel,ENABLE);
return 0;
#else
IIC_Start();
IIC_Send_Byte(SlaveAddress);
IIC_Wait_Ack();
IIC_Send_Byte(REG_Address);
IIC_Wait_Ack();
IIC_Send_Byte(REG_data);
IIC_Wait_Ack();
IIC_Stop();
#endif
}
u8 read8(u8 addr)
{
u8 ReceiveData = 0;
#ifdef HARDWARE_IIC
I2C_AcknowledgeConfig(I2C_Channel,ENABLE); //许应答模式
I2C_GenerateSTART(I2C_Channel,ENABLE);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_MODE_SELECT));
// I2C_Send7bitAddress(I2C_Channel,I2C_Read_ADDRESS,I2C_Direction_Transmitter);
// DELAY_US(60);
// while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// I2C_SendData(I2C_Channel,addr);
// while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// I2C_GenerateSTOP(I2C_Channel,ENABLE);
I2C_Send7bitAddress(I2C_Channel,I2C_Read_ADDRESS,I2C_Direction_Receiver);
DELAY_US(60);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_SendData(I2C_Channel,addr);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_BYTE_RECEIVED));
I2C_GenerateSTOP(I2C_Channel,ENABLE);
ReceiveData = I2C_ReceiveData(I2C_Channel);
return ReceiveData;
#else
IIC_Start();
IIC_Send_Byte(I2C_Write_ADDRESS);//I2C_Write_ADDRESS//I2C_Read_ADDRESS
IIC_Wait_Ack();
// DELAY_US(100);
IIC_Wait_Ack();
IIC_Send_Byte(addr);
IIC_Wait_Ack();
ReceiveData = IIC_Read_Byte(1);//data read error
IIC_Stop();
return ReceiveData;
#endif
}
void write8(u8 addr, u8 d)
{
#ifdef HARDWARE_IIC
I2C_AcknowledgeConfig(I2C_Channel,ENABLE); //
I2C_GenerateSTART(I2C_Channel,ENABLE);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C_Channel,I2C_Write_ADDRESS,I2C_Direction_Transmitter);
DELAY_US(60);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C_Channel,addr);
I2C_SendData(I2C_Channel,d);
while(!I2C_CheckEvent(I2C_Channel,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C_Channel,ENABLE);
#else
// IIC_Start();
// IIC_Send_Byte(I2C_Write_ADDRESS);
// IIC_Wait_Ack();
//
// // DELAY_US(60);
// IIC_Send_Byte(addr);
// IIC_Wait_Ack();
//
// IIC_Send_Byte(d);
// IIC_Wait_Ack();
// IIC_Stop();
I2C_ByteWrite(I2C_Write_ADDRESS, addr, d);
#endif
}
void setPWMFreq(float freq) //设置频率
{
int prescale;
int oldmode;
int newmode;
freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11).
prescale = (int)((25000000/(4096*freq))- 1);//-6
oldmode = read8(PCA9685_MODE1);
newmode = (oldmode&0x7F) | SLEEP_BIT; // sleep
write8(PCA9685_MODE1, newmode); // go to sleep PCA9685_MODE1 0x00
write8(PCA9685_PRESCALE, prescale); // set the prescaler PCA9685_PRESCALE 0x