Files
JBao_Heat_Pad_FW/apps/usr_periph/bsp_zc.c
T

193 lines
4.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************************
* @file bsp_zc.c
* @brief PA1 过零:MCPWM FPIN 双沿中断,沿到则回调切继电器
* @author cyWu <1917507415@qq.com>
* @date 2026.09.04
* @version V3.1.0
* @history
* - V3.1.0, 2026.09.04, cyWu, 状态收进 BspZcCtx_t,去掉无用计数与排障史注释
* - V3.0.0, 2026.09.04, cyWu, MCPWM FPIN 硬件边沿中断
******************************************************************************/
#include "system/includes.h"
#include "asm/gpio.h"
#include "asm/mcpwm.h"
#include "asm/hwi.h"
#include "asm/irq.h"
#include "asm/timer.h"
#include "bsp_zc.h"
#include "board_pin.h"
#include <string.h>
#define LOG_TAG_CONST APP
#define LOG_TAG "[BSP_ZC]"
#define LOG_INFO_ENABLE
#include "debug.h"
extern PWM_CH_REG *get_pwm_ch_reg(pwm_ch_num_type index);
typedef struct {
BspZcEdgeCb_t edge_cb;
volatile uint32_t edge_cnt;
volatile uint32_t last_edge_ms;
volatile uint8_t last_level;
uint8_t initialized;
} BspZcCtx_t;
static BspZcCtx_t s_zc;
/**
* @brief FPIN 边沿 ISR:清 pending、记沿、执行切变回调
* @note 中断上下文:禁止 printf / 写 VM / 切 BLE
* @return 无
*/
___interrupt
static void bsp_zc_interrupt(void)
{
if (JL_MCPWM->CH0_CON1 & BIT(15)) {
JL_MCPWM->CH0_CON1 |= BIT(14);
} else if (JL_MCPWM->CH1_CON1 & BIT(15)) {
JL_MCPWM->CH1_CON1 |= BIT(14);
} else if (JL_MCPWM->CH2_CON1 & BIT(15)) {
JL_MCPWM->CH2_CON1 |= BIT(14);
} else if (JL_MCPWM->CH3_CON1 & BIT(15)) {
JL_MCPWM->CH3_CON1 |= BIT(14);
} else {
return;
}
s_zc.edge_cnt++;
s_zc.last_edge_ms = (uint32_t)timer_get_ms();
s_zc.last_level = (uint8_t)gpio_read(BOARD_ZC_PIN);
if (s_zc.edge_cb) {
s_zc.edge_cb();
}
}
/**
* @brief 把 PA1 接到一个 FPIN 通道(上升沿或下降沿)
* @param index FPIN 通道 0~3
* @param rising 1=上升沿,0=下降沿
* @return 无
*/
static void bsp_zc_fpin_channel_init(u8 index, u8 rising)
{
PWM_CH_REG *pwm_reg;
if (index > 3) {
return;
}
if (rising) {
JL_MCPWM->FPIN_CON |= BIT(16 + index);
} else {
JL_MCPWM->FPIN_CON &= ~BIT(16 + index);
}
#if BOARD_ZC_FPIN_FILTER_EN
JL_MCPWM->FPIN_CON |= BIT(8 + index);
JL_MCPWM->FPIN_CON |= ((u32)BOARD_ZC_FPIN_FILTER & 0x3FUL);
#else
JL_MCPWM->FPIN_CON &= ~BIT(8 + index);
#endif
gpio_ich_sel_iutput_signal(BOARD_ZC_PIN,
(enum INPUT_CH_SIGNAL)(INPUT_CH_SIGNAL_MC_FPIN0 + index),
INPUT_CH_TYPE_GP_ICH);
request_irq(IRQ_MCPWM_CHX_IDX, 3, bsp_zc_interrupt, 0);
pwm_reg = get_pwm_ch_reg((pwm_ch_num_type)index);
pwm_reg->ch_con1 = BIT(14) | BIT(11) | BIT(4) | (index << 0);
JL_MCPWM->MCPWM_CON0 |= BIT(index);
}
/**
* @brief 初始化 PA1 输入并挂双沿 FPIN 中断
* @param cb 沿回调,NULL 则只计数
* @return 无
*/
void bsp_zc_init(BspZcEdgeCb_t cb)
{
if (s_zc.initialized) {
return;
}
memset(&s_zc, 0, sizeof(s_zc));
s_zc.edge_cb = cb;
gpio_set_die(BOARD_ZC_PIN, 1);
gpio_set_direction(BOARD_ZC_PIN, 1);
gpio_set_pull_up(BOARD_ZC_PIN, BOARD_ZC_PULL_UP);
gpio_set_pull_down(BOARD_ZC_PIN, BOARD_ZC_PULL_DOWN);
s_zc.last_level = (uint8_t)gpio_read(BOARD_ZC_PIN);
#if BOARD_ZC_USE_IRQ
bsp_zc_fpin_channel_init((u8)BOARD_ZC_FPIN_FALL_CH, 0);
#if BOARD_ZC_FPIN_BOTH_EDGE
bsp_zc_fpin_channel_init((u8)BOARD_ZC_FPIN_RISE_CH, 1);
#endif
#endif
s_zc.initialized = 1;
log_info("zc init irq=%d fall=%d rise=%d filt=%d lvl=%d\n",
BOARD_ZC_USE_IRQ, BOARD_ZC_FPIN_FALL_CH,
#if BOARD_ZC_FPIN_BOTH_EDGE
BOARD_ZC_FPIN_RISE_CH,
#else
-1,
#endif
BOARD_ZC_FPIN_FILTER_EN, (int)s_zc.last_level);
}
/**
* @brief 1ms 软件采样兜底(须由真实 1ms 定时器调用)
* @return 无
*/
void bsp_zc_scan_1ms(void)
{
uint8_t lvl;
if (!s_zc.initialized) {
return;
}
lvl = (uint8_t)gpio_read(BOARD_ZC_PIN);
if (lvl != s_zc.last_level) {
s_zc.last_level = lvl;
s_zc.edge_cnt++;
s_zc.last_edge_ms = (uint32_t)timer_get_ms();
if (s_zc.edge_cb) {
s_zc.edge_cb();
}
}
}
/**
* @brief 累计过零沿次数
* @return 沿计数
*/
uint32_t bsp_zc_edge_count(void)
{
return s_zc.edge_cnt;
}
/**
* @brief 最近一次沿的时间戳
* @return timer_get_ms()0=从未检测到
*/
uint32_t bsp_zc_last_edge_ms(void)
{
return s_zc.last_edge_ms;
}
/**
* @brief 当前 PA1 电平
* @return 0 或 1
*/
uint8_t bsp_zc_level(void)
{
return (uint8_t)gpio_read(BOARD_ZC_PIN);
}