KOP9967(高度集成化多通道智能驱动器集成电路)驱动
关于kop9967的驱动是基于hc32l136k8ta环境,kop9967 datasheet rev020版本。
性能及参数不详细赘述,直接上代码。驱动只提供了8路继电器的驱动 以及128ms的周期电平翻转维持,关于蜂鸣器驱动没有提及。
.c文件
#include "KOP9967_drive.h"
uint8_t T_Timer = 5;//KOP9967周期T
relaydef relayCondef;
/**************************************************
** 函数名称: void KOP9967IO_Init(void)
** 功能描述:kop9967 io初始化
** 输 入: void
** 输 出: void
***************************************************/
void KOP9967IO_Init(void)
{
stc_gpio_config_t stcGpioCfg;
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输出
stcGpioCfg.enDir = GpioDirOut;
///< 端口驱动能力配置->高驱动能力
stcGpioCfg.enDrv = GpioDrvL;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
stcGpioCfg.enCtrlMode = GpioAHB;
Gpio_Init(KOP9967GPIO_PORT, KOP9967GPIO_PIN, &stcGpioCfg);
}
/**************************************************
** 函数名称: void Ris_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint8_t Cycle)
** 功能描述:持续输出高电平
** 输 入: enPort IO Port口 enPin IO Pin脚 Cycle 持续时间
** 输 出:
***************************************************/
void Ris_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint16_t Cycle)
{
static uint16_t Cycle_Ris = 0;
if(Cycle == 0)
{
Gpio_SetIO(enPort, enPin);//高电平输出
}
else
{
while(Cycle_Ris < Cycle)
{
Gpio_SetIO(enPort, enPin);//高电平输出
Cycle_Ris++;
}
Cycle_Ris = 0;
}
}
/**************************************************
** 函数名称: void Fall_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint8_t Cycle)
** 功能描述:持续输出低电平
** 输 入: enPort IO Port口 enPin IO Pin脚 Cycle 持续时间
** 输 出:
***************************************************/
void Fall_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint16_t Cycle)
{
static uint16_t Cycle_Fall = 0;
if(Cycle == 0)
{
Gpio_ClrIO(enPort, enPin);//低电平输出
}
else
{
while(Cycle_Fall < Cycle)
{
Gpio_ClrIO(enPort, enPin);//低电平输出
Cycle_Fall++;
}
Cycle_Fall = 0;
}
}
/**************************************************
** 函数名称:void Out_Zero(void)
** 功能描述:输出 0
** 输 入:
** 输 出:
***************************************************/
void Out_Zero(void)
{
static uint8_t Period_State_Zero = 0x01;
while(Period_State_Zero < 0x04)
{
switch(Period_State_Zero)
{
case 0x01:
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_Zero = 0x02;
break;
case 0x02:
Fall_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_Zero = 0x03;
break;
case 0x03:
Fall_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_Zero = 0x04;
break;
default:break;
}
}
Period_State_Zero = 0x01;
}
/**************************************************
** 函数名称:void Out_One(void)
** 功能描述:输出 1
** 输 入:
** 输 出:
***************************************************/
void Out_One(void)
{
static uint8_t Period_State_One = 0x01;
while(Period_State_One < 0x04)
{
switch(Period_State_One)
{
case 0x01:
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_One = 0x02;
break;
case 0x02:
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_One = 0x03;
break;
case 0x03:
Fall_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Period_State_One = 0x04;
break;
default:break;
}
}
Period_State_One = 0x01;
}
/**************************************************
** 函数名称:void Out_One(void)
** 功能描述:输出 1
** 输 入:
** 输 出:
***************************************************/
void relayKOP9967_ControlHandler(uint8_t maskval)
{
uint8_t i,j=0;
rt_base_t level;
/*关全局中断*/#erro 非RT-Thread os 时删除此行代码
level = rt_hw_interrupt_disable();//为避免在多层嵌套的临界区产生异常
//level是进入临界段之前保存的 PRIMASK 的值
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,1);
Fall_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,1);
/*[Ld]*/
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
Ris_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
for(i=0;i<9;i++)
Fall_Edge(KOP9967GPIO_PORT, KOP9967GPIO_PIN,T_Timer);
/*[0]*/
Out_Zero();
/*[1]*/
Out_One();
/*[0]*/
Out_Zero();
/*[1]*/
Out_One();
/*[DA[0:15]]*/
for(i=0;i<8;i++)
{
switch(i)
{
case 0:
{
Out_One();//D0 保留位
//[1]:P7 输出低电平,[0]: P7 输出高阻态
if(maskval & 1<<i) //D1 低电平 继电器吸合
{
Out_One();
}
else //D1 高阻态 继电器断开
{
Out_Zero();
j += 1;
}
}break;
case 1:
{
Out_One();//D2 蜂鸣器分频设置 [0]:1/2 ,[1]: 保留
//[1]:P6 输出低电平,[0]: P6 输出高阻态
if(maskval & 1<<i)
{
Out_One();//D3 低电平 继电器吸合
}
else
{
Out_Zero();//D3 高阻态 继电器断开
j += 1;
}
}break;
case 2:
{
Out_One();//D4 普通模式输出保持最长时间设置位 1
//[1]:P5 输出低电平,[0]: P5 输出高阻态
if(maskval & 1<<i)
{
Out_One();//D5 低电平 继电器吸合
}
else
{
Out_Zero();//D5 高阻态 继电器断开
j += 1;
}
}break;
case 3:
{
Out_One();//D6 普通模式输出保持最长时间设置位 0
//[1]:P4 输出低电平,[0]: P4 输出高阻态
if(maskval & 1<<i)
{
Out_One();//D7 低电平 继电器吸合
}
else
{
Out_Zero();//D7 高阻态 继电器断开
j += 1;
}
}break;
case 4:
{
Out_Zero();//D8 和弦使能设置: [BuzEn] = 1: [0]:和弦关,[1]: 和弦开
//[1]:P3 输出低电平,[0]: P3 输出高阻态
if(maskval & 1<<i)
{
Out_One();//D9 低电平 继电器吸合
j += 1;
}
else
{
Out_Zero();//D9 高阻态 继电器断开
}
}break;
case 5:
{
//D10:D11 = [1][0] P2 输出高电平
//D10:D11 = [0][1] P2 输出低电平
//D10:D11 = [0][0] P2 输出高阻态
if(maskval & 1<<i) //低电平 继电器吸合
{
Out_Zero();//D10
Out_One();//D11
j += 1;
}
else //高阻态 继电器断开
{
Out_Zero();//D10
Out_Zero();//D11
}
}break;
case 6:
{
//D12:D13 = [1][0] P1 输出高电平
//D12:D13 = [0][1] P1 输出低电平
//D12:D13 = [0][0] P1 输出高阻态
if(maskval & 1<<i) //低电平 继电器吸合
{
Out_Zero();//D12
Out_One();//D13
j += 1;
}
else //高阻态 继电器断开
{
Out_Zero();//D12
Out_Zero();//D13
}
}break;
case 7:
{
//D14:D15 = [1][0] P0 输出高电平
//D14:D15 = [0][1] P0 输出低电平
//D14:D15 = [0][0] P0 输出高阻态
if(maskval & 1<<i) //低电平 继电器吸合
{
Out_Zero();//D14
Out_One();//D15
j += 1;
}
else //高阻态 继电器断开
{
Out_Zero();//D14
Out_Zero();//D15
}
}break;
default:break;
}
}
/*[BuzEn]*/
Out_Zero();//buz禁止
/*[CRC]*///确保“1”的个数为偶数
if(j%2)
Out_One();
else
Out_Zero();
/*[end]*/
Out_Zero();
/*[Buz_Freq]*/
Out_Zero();
/*开全局中断*/#erro 非RT-Thread os 时删除此行代码//根据传入参数level的状态来设置PRIMASK的值
rt_hw_interrupt_enable(level);//恢复全局中断
}
/**************************************************
** 函数名称:void relayControl_KOP9967_Update(const relaydef *relay)
** 功能描述:kop9967驱动继电器函数 此函数应放在调用时间小于128ms的线程中
以保证kop9967各输出引脚状态保持不中断 当mcu不需要更新继电器
状态时将产生一个周期翻转的电平以锁存继电器状态并且周期越小越好 暂定10ms
** 输 入:void
** 输 出:void
***************************************************/
void relayControl_KOP9967_Update(relaydef *relay)
{
static uint8_t tmp = 0;
static uint8_t cnt = 0;
if(relay->updateSW == R_UPDATE)//发生更新
{
cnt += 1;
if(cnt > 150)//1.5s
{
cnt = 0;
relay->updateSW = R_CONTINUE;
relayKOP9967_ControlHandler(relay->updateTY);
}
else
{
!!/*此处的产生的周期电平翻转对于在实时性要求非较高时适用 但对于外设宽裕的条件下应采用硬件产生的方式*/
/*code start*/
tmp ^= 1;
Gpio_WriteOutputIO(KOP9967GPIO_PORT,KOP9967GPIO_PIN,tmp);
/*code end*/
}
}
else//驱动中配置最长保持时间为128ms 所以需要在这个时间内完成翻转
{
cnt = 0;
!!/*此处的产生的周期电平翻转对于在实时性要求非较高时适用 但对于外设宽裕的条件下应采用硬件产生的方式*/
/*code start*/
tmp ^= 1;
Gpio_WriteOutputIO(KOP9967GPIO_PORT,KOP9967GPIO_PIN,tmp);
/*code end*/
}
}
#erro 此处贴出硬件产生的方式 当然可以使用pwm的方式 ##注意pwm的周期应小于2cly(上文提到的2*128ms)
此处和上文的软件翻转二选一!
!!
void TIM1_IRQHandler(void)
{
static volatile uint8_t tmp = 0;
rt_interrupt_enter();
if(TRUE == Bt_GetIntFlag(TIM1,BtUevIrq))
{
Bt_ClearIntFlag(TIM1,BtUevIrq);
tmp ^= 1;
Gpio_WriteOutputIO(KOP9967GPIO_PORT,KOP9967GPIO_PIN,tmp);
}
rt_interrupt_leave();
}
.h文件
#ifndef KOP9967_DRIVE_H
#define KOP9967_DRIVE_H
#include "gpio.h"
#include "app_task.h"
#define KOP9967GPIO_PORT GpioPortC
#define KOP9967GPIO_PIN GpioPin4
#define R_UPDATE 1
#define R_CONTINUE 0
typedef enum
{
relay_heat=0x80,
relay_lowspeed=0x40,
relay_midspeed=0x20,
relay_highspeed=0x10,
relay_cold=0x08,
relay_hot=0x04,
}updatetyenum;
typedef struct
{
uint8_t updateSW;
updatetyenum updateTY;
}relaydef;
extern relaydef relayCondef;
void KOP9967IO_Init(void);
void Ris_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint16_t Cycle);
void Fall_Edge(en_gpio_port_t enPort, en_gpio_pin_t enPin,uint16_t Cycle);
void Out_Zero(void);
void Out_One(void);
void relayKOP9967_ControlHandler(uint8_t maskval);
void relayControl_KOP9967_Update(relaydef *relay);
#endif