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