KOP9967(高度集成的多通道智能驱动集成电路)驱动
关于kop基于9967的驱动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