P0功能已实现,按键、LED、过零检测、配网、OTA都已正常实现
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
#include "asm/mcpwm.h"
|
||||
#include "asm/clock.h"
|
||||
#include "asm/gpio.h"
|
||||
|
||||
|
||||
|
||||
/******************************* 外部GPIO引脚中断参考代码 ***************************/
|
||||
|
||||
void (*io_isr_cbfun)(u8 index) = NULL;
|
||||
void set_io_ext_interrupt_cbfun(void (*cbfun)(u8 index))
|
||||
{
|
||||
io_isr_cbfun = cbfun;
|
||||
}
|
||||
___interrupt
|
||||
void io_interrupt(void)
|
||||
{
|
||||
u32 io_index = -1;
|
||||
if (JL_MCPWM->CH0_CON1 & BIT(15)) {
|
||||
JL_MCPWM->CH0_CON1 |= BIT(14);
|
||||
io_index = 0;
|
||||
} else if (JL_MCPWM->CH1_CON1 & BIT(15)) {
|
||||
JL_MCPWM->CH1_CON1 |= BIT(14);
|
||||
io_index = 1;
|
||||
} else if (JL_MCPWM->CH2_CON1 & BIT(15)) {
|
||||
JL_MCPWM->CH2_CON1 |= BIT(14);
|
||||
io_index = 2;
|
||||
} else if (JL_MCPWM->CH3_CON1 & BIT(15)) {
|
||||
JL_MCPWM->CH3_CON1 |= BIT(14);
|
||||
io_index = 3;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (io_isr_cbfun) {
|
||||
io_isr_cbfun(io_index);
|
||||
}
|
||||
}
|
||||
void io_ext_interrupt_init(u8 index, u8 port, u8 trigger_mode)
|
||||
{
|
||||
if (port > IO_PORT_MAX) {
|
||||
return;
|
||||
}
|
||||
gpio_set_die(port, 1);
|
||||
gpio_set_direction(port, 1);
|
||||
if (trigger_mode) {
|
||||
gpio_set_pull_up(port, 1);
|
||||
gpio_set_pull_down(port, 0);
|
||||
JL_MCPWM->FPIN_CON &= ~BIT(16 + index);//下降沿触发
|
||||
} else {
|
||||
gpio_set_pull_up(port, 0);
|
||||
gpio_set_pull_down(port, 1);
|
||||
JL_MCPWM->FPIN_CON |= BIT(16 + index);//上升沿触发
|
||||
}
|
||||
JL_MCPWM->FPIN_CON |= BIT(8 + index);//开启滤波
|
||||
JL_MCPWM->FPIN_CON |= (0b111111 << 0); //滤波时间 = 16 * 64 / hsb_clk (单位:s)
|
||||
|
||||
gpio_ich_sel_iutput_signal(port, INPUT_CH_SIGNAL_MC_FPIN0 + index, INPUT_CH_TYPE_GP_ICH);
|
||||
request_irq(IRQ_MCPWM_CHX_IDX, 3, io_interrupt, 0); //注册中断函数
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(index);
|
||||
pwm_reg->ch_con1 = BIT(14) | BIT(11) | BIT(4) | (index << 0);
|
||||
JL_MCPWM->MCPWM_CON0 |= BIT(index);
|
||||
#if 0
|
||||
printf("JL_MCPWM->CH%d_CON1 = 0x%x\n", index, pwm_reg->ch_con1);
|
||||
printf("JL_MCPWM->FPIN_CON = 0x%x\n", JL_MCPWM->FPIN_CON);
|
||||
printf("JL_MCPWM->MCPWM_CON0 = 0x%x\n", JL_MCPWM->MCPWM_CON0);
|
||||
printf("JL_IOMAP->ICH_CON0 = 0x%x\n", JL_IOMAP->ICH_CON0);
|
||||
printf("JL_IOMAP->ICH_CON1 = 0x%x\n", JL_IOMAP->ICH_CON1);
|
||||
printf("JL_IOMAP->ICH_CON2 = 0x%x\n", JL_IOMAP->ICH_CON2);
|
||||
printf("JL_IOMAP->ICH_CON3 = 0x%x\n", JL_IOMAP->ICH_CON3);
|
||||
printf("JL_IMAP->FI_GP_ICH0 = %d\n", JL_IMAP->FI_GP_ICH0);
|
||||
printf("JL_IMAP->FI_GP_ICH1 = %d\n", JL_IMAP->FI_GP_ICH1);
|
||||
printf("JL_IMAP->FI_GP_ICH2 = %d\n", JL_IMAP->FI_GP_ICH2);
|
||||
printf("JL_IMAP->FI_GP_ICH3 = %d\n", JL_IMAP->FI_GP_ICH3);
|
||||
printf("JL_IMAP->FI_GP_ICH4 = %d\n", JL_IMAP->FI_GP_ICH4);
|
||||
printf("JL_IMAP->FI_GP_ICH5 = %d\n", JL_IMAP->FI_GP_ICH5);
|
||||
printf("JL_IMAP->FI_GP_ICH6 = %d\n", JL_IMAP->FI_GP_ICH6);
|
||||
printf("JL_IMAP->FI_GP_ICH7 = %d\n", JL_IMAP->FI_GP_ICH7);
|
||||
printf("JL_IMAP->FI_GP_ICH8 = %d\n", JL_IMAP->FI_GP_ICH8);
|
||||
printf("JL_IMAP->FI_GP_ICH9 = %d\n", JL_IMAP->FI_GP_ICH9);
|
||||
#endif // 0
|
||||
}
|
||||
void io_ext_interrupt_close(u8 index, u8 port)
|
||||
{
|
||||
if (port > IO_PORT_MAX) {
|
||||
return;
|
||||
}
|
||||
gpio_set_die(port, 0);
|
||||
gpio_set_direction(port, 1);
|
||||
gpio_set_pull_up(port, 0);
|
||||
gpio_set_pull_down(port, 0);
|
||||
gpio_ich_disable_iutput_signal(port, INPUT_CH_SIGNAL_MC_FPIN0 + index, INPUT_CH_TYPE_GP_ICH);
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(index);
|
||||
pwm_reg->ch_con1 = BIT(14);
|
||||
}
|
||||
|
||||
///////////// 使用举例如下 //////////////////
|
||||
void my_io_isr_cbfun(u8 index)
|
||||
{
|
||||
printf("io index --> %d Hello world !\n", index);
|
||||
}
|
||||
void io_ext_interrupt_test(void)
|
||||
{
|
||||
set_io_ext_interrupt_cbfun(my_io_isr_cbfun);
|
||||
io_ext_interrupt_init(0, IO_PORTA_04, 1);
|
||||
io_ext_interrupt_init(1, IO_PORTB_01, 1);
|
||||
io_ext_interrupt_init(2, IO_PORTC_02, 1);
|
||||
io_ext_interrupt_init(3, IO_PORTG_01, 1);
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
#include "asm/mcpwm.h"
|
||||
#include "asm/clock.h"
|
||||
#include "asm/gpio.h"
|
||||
|
||||
#define MCPWM_DEBUG_ENABLE 1
|
||||
#if MCPWM_DEBUG_ENABLE
|
||||
#define mcpwm_debug(fmt, ...) printf("[MCPWM] "fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define mcpwm_debug(...)
|
||||
#endif
|
||||
|
||||
#define MCPWM_CLK clk_get("mcpwm")
|
||||
|
||||
|
||||
|
||||
/********************************硬件PWM相关函数**************************/
|
||||
|
||||
|
||||
PWM_TIMER_REG *get_pwm_timer_reg(pwm_ch_num_type index)
|
||||
{
|
||||
PWM_TIMER_REG *reg = NULL;
|
||||
switch (index) {
|
||||
case pwm_ch0:
|
||||
reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR0_CON));
|
||||
break;
|
||||
case pwm_ch1:
|
||||
reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR1_CON));
|
||||
break;
|
||||
case pwm_ch2:
|
||||
reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR2_CON));
|
||||
break;
|
||||
case pwm_ch3:
|
||||
reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR3_CON));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
PWM_CH_REG *get_pwm_ch_reg(pwm_ch_num_type index)
|
||||
{
|
||||
PWM_CH_REG *reg = NULL;
|
||||
switch (index) {
|
||||
case pwm_ch0:
|
||||
reg = (PWM_CH_REG *)(&(JL_MCPWM->CH0_CON0));
|
||||
break;
|
||||
case pwm_ch1:
|
||||
reg = (PWM_CH_REG *)(&(JL_MCPWM->CH1_CON0));
|
||||
break;
|
||||
case pwm_ch2:
|
||||
reg = (PWM_CH_REG *)(&(JL_MCPWM->CH2_CON0));
|
||||
break;
|
||||
case pwm_ch3:
|
||||
reg = (PWM_CH_REG *)(&(JL_MCPWM->CH3_CON0));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
static u8 clk_in_io = IO_PORTC_02;
|
||||
/*
|
||||
* @brief 更改MCPWM的频率
|
||||
* @parm frequency 频率
|
||||
*/
|
||||
void mcpwm_set_frequency(pwm_ch_num_type ch, pwm_aligned_mode_type align, u32 frequency)
|
||||
{
|
||||
PWM_TIMER_REG *reg = get_pwm_timer_reg(ch);
|
||||
if (reg == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
reg->tmr_con = 0;
|
||||
reg->tmr_cnt = 0;
|
||||
reg->tmr_pr = 0;
|
||||
|
||||
u32 i = 0;
|
||||
u32 mcpwm_div_clk = 0;
|
||||
u32 mcpwm_tmr_pr = 0;
|
||||
u32 mcpwm_fre_min = 0;
|
||||
u32 clk = MCPWM_CLK;
|
||||
for (i = 0; i < 16; i++) {
|
||||
mcpwm_fre_min = clk / (65536 * (1 << i));
|
||||
if ((frequency >= mcpwm_fre_min) || (i == 15)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
reg->tmr_con |= (i << 3); //div 2^i
|
||||
mcpwm_div_clk = clk / (1 << i);
|
||||
if (frequency == 0) {
|
||||
mcpwm_tmr_pr = 0;
|
||||
} else {
|
||||
if (align == pwm_center_aligned) { //中心对齐
|
||||
mcpwm_tmr_pr = mcpwm_div_clk / (frequency * 2) - 1;
|
||||
} else {
|
||||
mcpwm_tmr_pr = mcpwm_div_clk / frequency - 1;
|
||||
}
|
||||
}
|
||||
reg->tmr_pr = mcpwm_tmr_pr;
|
||||
//timer mode
|
||||
if (align == pwm_center_aligned) { //中心对齐
|
||||
reg->tmr_con |= 0b10;
|
||||
} else {
|
||||
reg->tmr_con |= 0b01;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 old_mcpwm_clk = 0;
|
||||
static void clock_critical_enter(void)
|
||||
{
|
||||
old_mcpwm_clk = clk_get("mcpwm");
|
||||
}
|
||||
static void clock_critical_exit(void)
|
||||
{
|
||||
u32 new_mcpwm_clk = clk_get("mcpwm");
|
||||
if (new_mcpwm_clk == old_mcpwm_clk) {
|
||||
return;
|
||||
}
|
||||
PWM_CH_REG *pwm_reg = NULL;
|
||||
PWM_TIMER_REG *timer_reg = NULL;
|
||||
for (u8 ch = 0; ch < 4; ch++) {
|
||||
if (JL_MCPWM->MCPWM_CON0 & BIT(ch + 8)) {
|
||||
pwm_reg = get_pwm_ch_reg(ch);
|
||||
timer_reg = get_pwm_timer_reg(ch);
|
||||
if (new_mcpwm_clk > old_mcpwm_clk) {
|
||||
timer_reg->tmr_pr = timer_reg->tmr_pr * (new_mcpwm_clk / old_mcpwm_clk);
|
||||
pwm_reg->ch_cmpl = pwm_reg->ch_cmpl * (new_mcpwm_clk / old_mcpwm_clk);
|
||||
} else {
|
||||
timer_reg->tmr_pr = timer_reg->tmr_pr / (old_mcpwm_clk / new_mcpwm_clk);
|
||||
pwm_reg->ch_cmpl = pwm_reg->ch_cmpl / (old_mcpwm_clk / new_mcpwm_clk);
|
||||
}
|
||||
pwm_reg->ch_cmph = pwm_reg->ch_cmpl;
|
||||
}
|
||||
}
|
||||
}
|
||||
CLOCK_CRITICAL_HANDLE_REG(mcpwm, clock_critical_enter, clock_critical_exit)
|
||||
|
||||
/*
|
||||
* @brief 设置一个通道的占空比
|
||||
* @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2
|
||||
* @parm duty 占空比:0 ~ 10000 对应 0% ~ 100%
|
||||
*/
|
||||
void mcpwm_set_duty(pwm_ch_num_type pwm_ch, u16 duty)
|
||||
{
|
||||
PWM_TIMER_REG *timer_reg = get_pwm_timer_reg(pwm_ch);
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch);
|
||||
|
||||
if (pwm_reg && timer_reg) {
|
||||
pwm_reg->ch_cmpl = timer_reg->tmr_pr * duty / 10000;
|
||||
pwm_reg->ch_cmph = pwm_reg->ch_cmpl;
|
||||
timer_reg->tmr_cnt = 0;
|
||||
timer_reg->tmr_con |= 0b01;
|
||||
if (duty == 10000) {
|
||||
timer_reg->tmr_cnt = 0;
|
||||
timer_reg->tmr_con &= ~(0b11);
|
||||
} else if (duty == 0) {
|
||||
timer_reg->tmr_cnt = pwm_reg->ch_cmpl;
|
||||
timer_reg->tmr_con &= ~(0b11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief 打开或者关闭一个时基
|
||||
* @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2
|
||||
* @parm enable 1:打开 0:关闭
|
||||
*/
|
||||
void mctimer_ch_open_or_close(pwm_ch_num_type pwm_ch, u8 enable)
|
||||
{
|
||||
if (pwm_ch > pwm_ch_max) {
|
||||
return;
|
||||
}
|
||||
if (enable) {
|
||||
JL_MCPWM->MCPWM_CON0 |= BIT(pwm_ch + 8); //TnEN
|
||||
} else {
|
||||
JL_MCPWM->MCPWM_CON0 &= (~BIT(pwm_ch + 8)); //TnDIS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief 打开或者关闭一个通道
|
||||
* @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2
|
||||
* @parm enable 1:打开 0:关闭
|
||||
*/
|
||||
void mcpwm_ch_open_or_close(pwm_ch_num_type pwm_ch, u8 enable)
|
||||
{
|
||||
if (pwm_ch >= pwm_ch_max) {
|
||||
return;
|
||||
}
|
||||
if (enable) {
|
||||
JL_MCPWM->MCPWM_CON0 |= BIT(pwm_ch); //PWMnEN
|
||||
} else {
|
||||
JL_MCPWM->MCPWM_CON0 &= (~BIT(pwm_ch)); //PWMnDIS
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief 关闭MCPWM模块
|
||||
*/
|
||||
void mcpwm_open(pwm_ch_num_type pwm_ch)
|
||||
{
|
||||
if (pwm_ch >= pwm_ch_max) {
|
||||
return;
|
||||
}
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch);
|
||||
pwm_reg->ch_con1 &= ~(0b111 << 8);
|
||||
pwm_reg->ch_con1 |= (pwm_ch << 8); //sel mctmr
|
||||
mcpwm_ch_open_or_close(pwm_ch, 1);
|
||||
mctimer_ch_open_or_close(pwm_ch, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief 关闭MCPWM模块
|
||||
*/
|
||||
void mcpwm_close(pwm_ch_num_type pwm_ch)
|
||||
{
|
||||
mctimer_ch_open_or_close(pwm_ch, 0);
|
||||
mcpwm_ch_open_or_close(pwm_ch, 0);
|
||||
}
|
||||
|
||||
|
||||
void log_pwm_info(pwm_ch_num_type pwm_ch)
|
||||
{
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch);
|
||||
PWM_TIMER_REG *timer_reg = get_pwm_timer_reg(pwm_ch);
|
||||
mcpwm_debug("tmr%d con0 = 0x%x", pwm_ch, timer_reg->tmr_con);
|
||||
mcpwm_debug("tmr%d pr = 0x%x", pwm_ch, timer_reg->tmr_pr);
|
||||
mcpwm_debug("pwm ch%d_con0 = 0x%x", pwm_ch, pwm_reg->ch_con0);
|
||||
mcpwm_debug("pwm ch%d_con1 = 0x%x", pwm_ch, pwm_reg->ch_con1);
|
||||
mcpwm_debug("pwm ch%d_cmph = 0x%x, pwm ch%d_cmpl = 0x%x", pwm_ch, pwm_reg->ch_cmph, pwm_ch, pwm_reg->ch_cmpl);
|
||||
mcpwm_debug("MCPWM_CON0 = 0x%x", JL_MCPWM->MCPWM_CON0);
|
||||
mcpwm_debug("mcpwm clk = %d", MCPWM_CLK);
|
||||
}
|
||||
|
||||
void mcpwm_init(struct pwm_platform_data *arg)
|
||||
{
|
||||
//set output IO
|
||||
PWM_CH_REG *pwm_reg = get_pwm_ch_reg(arg->pwm_ch_num);
|
||||
if (pwm_reg == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//set mctimer frequency
|
||||
mcpwm_set_frequency(arg->pwm_ch_num, arg->pwm_aligned_mode, arg->frequency);
|
||||
|
||||
pwm_reg->ch_con0 = 0;
|
||||
|
||||
if (arg->complementary_en) { //是否互补
|
||||
pwm_reg->ch_con0 &= ~(BIT(5) | BIT(4));
|
||||
pwm_reg->ch_con0 |= BIT(5); //L_INV
|
||||
} else {
|
||||
pwm_reg->ch_con0 &= ~(BIT(5) | BIT(4));
|
||||
}
|
||||
|
||||
mcpwm_open(arg->pwm_ch_num); //mcpwm enable
|
||||
//set duty
|
||||
mcpwm_set_duty(arg->pwm_ch_num, arg->duty);
|
||||
|
||||
//H:
|
||||
if (arg->h_pin < IO_MAX_NUM) { //任意引脚
|
||||
pwm_reg->ch_con0 |= BIT(2); //H_EN
|
||||
gpio_och_sel_output_signal(arg->h_pin, OUTPUT_CH_SIGNAL_MC_PWM0_H + 2 * arg->pwm_ch_num);
|
||||
gpio_set_direction(arg->h_pin, 0); //DIR output
|
||||
}
|
||||
//L:
|
||||
if (arg->l_pin < IO_MAX_NUM) { //任意引脚
|
||||
pwm_reg->ch_con0 |= BIT(3); //L_EN
|
||||
gpio_och_sel_output_signal(arg->l_pin, OUTPUT_CH_SIGNAL_MC_PWM0_L + 2 * arg->pwm_ch_num);
|
||||
gpio_set_direction(arg->l_pin, 0); //DIR output
|
||||
}
|
||||
|
||||
log_pwm_info(arg->pwm_ch_num);
|
||||
}
|
||||
|
||||
#define PWM_CH0_ENABLE 0
|
||||
#define PWM_CH1_ENABLE 0
|
||||
#define PWM_CH2_ENABLE 0
|
||||
#define PWM_CH3_ENABLE 0
|
||||
void usr_mcpwm_init(void)
|
||||
{
|
||||
struct pwm_platform_data pwm_p_data;
|
||||
|
||||
#if PWM_CH0_ENABLE
|
||||
pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐
|
||||
pwm_p_data.pwm_ch_num = pwm_ch0; //通道号
|
||||
pwm_p_data.frequency = 500; //1KHz
|
||||
pwm_p_data.duty = 0; //占空比50%
|
||||
pwm_p_data.h_pin = IO_PORTA_06; //任意引脚
|
||||
pwm_p_data.l_pin = -1; //任意引脚,不需要就填-1
|
||||
pwm_p_data.complementary_en = 0; //两个引脚的波形, 0: 同步, 1: 互补,互补波形的占空比体现在H引脚上
|
||||
mcpwm_init(&pwm_p_data);
|
||||
#endif
|
||||
#if PWM_CH1_ENABLE
|
||||
pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐
|
||||
pwm_p_data.pwm_ch_num = pwm_ch1; //通道号
|
||||
pwm_p_data.frequency = 500; //1KHz
|
||||
pwm_p_data.duty = 0; //占空比25%
|
||||
pwm_p_data.h_pin = IO_PORTA_08; //任意引脚
|
||||
pwm_p_data.l_pin = -1; //任意引脚,不需要就填-1
|
||||
pwm_p_data.complementary_en = 0; //两个引脚的波形, 0: 同步, 1: 互补,互补波形的占空比体现在H引脚上
|
||||
mcpwm_init(&pwm_p_data);
|
||||
#endif
|
||||
#if PWM_CH2_ENABLE
|
||||
pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐
|
||||
pwm_p_data.pwm_ch_num = pwm_ch2; //通道号
|
||||
pwm_p_data.frequency = 10000; //10KHz
|
||||
pwm_p_data.duty = 5000; //占空比50%
|
||||
pwm_p_data.h_pin = IO_PORTA_03; //任意引脚
|
||||
pwm_p_data.l_pin = -1; //任意引脚,不需要就填-1
|
||||
mcpwm_init(&pwm_p_data);
|
||||
#endif
|
||||
#if PWM_CH3_ENABLE
|
||||
pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐
|
||||
pwm_p_data.pwm_ch_num = pwm_ch3; //通道号
|
||||
pwm_p_data.frequency = 10000; //10KHz
|
||||
pwm_p_data.duty = 7500; //占空比75%
|
||||
pwm_p_data.h_pin = IO_PORTA_04; //任意引脚
|
||||
pwm_p_data.l_pin = IO_PORTA_05; //任意引脚,不需要就填-1
|
||||
pwm_p_data.complementary_en = 0; //两个引脚的波形, 0: 同步, 1: 互补,互补波形的占空比体现在H引脚上
|
||||
mcpwm_init(&pwm_p_data);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extern void clk_out(u8 gpio, enum CLK_OUT_SOURCE clk);
|
||||
clk_out(IO_PORTA_07, LSB_CLK_OUT);
|
||||
extern void wdt_clear();
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/******************************* 用timer做pwm的参考代码 ***************************/
|
||||
|
||||
/**
|
||||
* @param JL_TIMERx : JL_TIMER0/1/2/3
|
||||
* @param pwm_io : JL_PORTA_01, JL_PORTB_02,,,等等,支持任意普通IO
|
||||
* @param fre : 频率,单位Hz
|
||||
* @param duty : 初始占空比,0~10000对应0~100%
|
||||
*/
|
||||
void timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 pwm_io, u32 fre, u32 duty)
|
||||
{
|
||||
switch ((u32)JL_TIMERx) {
|
||||
case (u32)JL_TIMER0 :
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER0_PWM);
|
||||
break;
|
||||
case (u32)JL_TIMER1 :
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER1_PWM);
|
||||
break;
|
||||
case (u32)JL_TIMER2 :
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER2_PWM);
|
||||
break;
|
||||
case (u32)JL_TIMER3 :
|
||||
bit_clr_ie(IRQ_TIME3_IDX);
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER3_PWM);
|
||||
break;
|
||||
case (u32)JL_TIMER4 :
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER4_PWM);
|
||||
break;
|
||||
case (u32)JL_TIMER5 :
|
||||
gpio_och_sel_output_signal(pwm_io, OUTPUT_CH_SIGNAL_TIMER5_PWM);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
u32 u_clk = 24000000;
|
||||
//初始化timer
|
||||
JL_TIMERx->CON = 0;
|
||||
JL_TIMERx->CON |= (0b110 << 10); //时钟源选择STD_24M时钟源
|
||||
JL_TIMERx->CON |= (0b0001 << 4); //时钟源再4分频
|
||||
JL_TIMERx->CNT = 0; //清计数值
|
||||
JL_TIMERx->PRD = u_clk / (4 * fre); //设置周期
|
||||
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000; //设置初始占空比,0~10000对应0~100%
|
||||
JL_TIMERx->CON |= (0b01 << 0); //计数模式
|
||||
JL_TIMERx->CON |= BIT(8); //PWM使能
|
||||
//设置引脚状态
|
||||
gpio_set_die(pwm_io, 1);
|
||||
gpio_set_pull_up(pwm_io, 0);
|
||||
gpio_set_pull_down(pwm_io, 0);
|
||||
gpio_set_direction(pwm_io, 0);
|
||||
|
||||
printf("JL_TIMERx->PRD = 0x%x\n", JL_TIMERx->PRD);
|
||||
printf("JL_TIMERx->CON = 0x%x\n", JL_TIMERx->CON);
|
||||
}
|
||||
|
||||
|
||||
void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 duty)
|
||||
{
|
||||
JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000; //0~10000对应0~100%
|
||||
}
|
||||
|
||||
void timer_pwm_test(void)///GPIO随意映射
|
||||
{
|
||||
timer_pwm_init(JL_TIMER2, IO_PORTC_03, 10000, 7000);
|
||||
timer_pwm_init(JL_TIMER3, IO_PORTG_04, 1000, 2000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "app_config.h"
|
||||
#include "key_event_deal.h"
|
||||
#include "system/includes.h"
|
||||
#include "tone_player.h"
|
||||
#include "app_task.h"
|
||||
#include "tone_player.h"
|
||||
#include "media/includes.h"
|
||||
#include "system/sys_time.h"
|
||||
//#include "alarm.h"
|
||||
#include "clock_cfg.h"
|
||||
#include "rtc_app.h"
|
||||
|
||||
/*************************************************************
|
||||
此文件函数主要是rtc
|
||||
|
||||
**************************************************************/
|
||||
#include "usr_jb_global.h"
|
||||
|
||||
#if TCFG_APP_RTC_EN
|
||||
|
||||
|
||||
|
||||
#define LOG_TAG_CONST APP_RTC
|
||||
#define LOG_TAG "[APP_RTC]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
struct rtc_opr {
|
||||
void *dev_handle;
|
||||
/*u8 rtc_set_mode;
|
||||
u8 rtc_pos;
|
||||
u8 alm_enable;
|
||||
u8 alm_num;
|
||||
struct sys_time set_time;*/
|
||||
};
|
||||
|
||||
static struct rtc_opr *__this = NULL;
|
||||
|
||||
static void rtc_app_init()
|
||||
{
|
||||
if (!__this) {
|
||||
__this = zalloc(sizeof(struct rtc_opr));
|
||||
ASSERT(__this, "%s %di \n", __func__, __LINE__);
|
||||
__this->dev_handle = dev_open("rtc", NULL);
|
||||
if (!__this->dev_handle) {
|
||||
ASSERT(0, "%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------*/
|
||||
/**@brief rtc 退出
|
||||
@param 无
|
||||
@return
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void rtc_task_close()
|
||||
{
|
||||
if (__this) {
|
||||
if (__this->dev_handle) {
|
||||
dev_close(__this->dev_handle);
|
||||
__this->dev_handle = NULL;
|
||||
}
|
||||
free(__this);
|
||||
__this = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------*/
|
||||
/**@brief rtc 启动
|
||||
@param 无
|
||||
@return
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void rtc_task_start()
|
||||
{
|
||||
rtc_app_init();
|
||||
}
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------*/
|
||||
/**@brief rtc 主任务
|
||||
@param 无
|
||||
@return 无
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void usr_jb_rtc_init()
|
||||
{
|
||||
rtc_task_start();
|
||||
}
|
||||
|
||||
struct sys_time usr_jb_current_time;
|
||||
|
||||
|
||||
// 计算某年某月某日是星期几(返回1-7对应周一到周日)
|
||||
uint8_t calculateWeekday(uint16_t year, uint8_t month, uint8_t day)
|
||||
{
|
||||
if (month < 3) {
|
||||
month += 12;
|
||||
year -= 1;
|
||||
}
|
||||
uint16_t century = year / 100;
|
||||
uint16_t yearInCentury = year % 100;
|
||||
uint16_t h = (day + (13 * (month + 1)) / 5 + yearInCentury + yearInCentury / 4 + century / 4 + 5 * century) % 7;
|
||||
uint8_t weekday = (h + 5) % 7 + 1;
|
||||
return weekday;
|
||||
}
|
||||
void usr_rtc_read_time()
|
||||
{
|
||||
static u8 cnt=0;
|
||||
cnt++;
|
||||
if(cnt>2)
|
||||
{
|
||||
cnt=0;
|
||||
read_sys_time(&usr_jb_current_time);
|
||||
if((usr_jb_current_time.year<2025)||(usr_jb_current_time.year>2098))
|
||||
{
|
||||
usr_var.usr_time_set_flag=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
usr_var.usr_time_set_flag=1;
|
||||
}
|
||||
|
||||
if(usr_var.usr_time_set_flag)
|
||||
{
|
||||
usr_var.usr_cureent_utc=convertToUtcTimestamp(usr_jb_current_time.year,usr_jb_current_time.month,usr_jb_current_time.day,usr_jb_current_time.hour,usr_jb_current_time.min,usr_jb_current_time.sec);
|
||||
if(usr_var.usr_cureent_utc)
|
||||
{
|
||||
if(usr_var.usr_cureent_utc>usr_var.usr_timezoneOffset)usr_var.usr_cureent_utc=usr_var.usr_cureent_utc-usr_var.usr_timezoneOffset;
|
||||
}
|
||||
usr_var.usr_week_data=calculateWeekday(usr_jb_current_time.year,usr_jb_current_time.month,usr_jb_current_time.day);
|
||||
|
||||
usr_jb_ignore_alft();
|
||||
}
|
||||
|
||||
/*printf("time: %d-%d-%d %d:%d:%d",
|
||||
usr_jb_current_time.year,
|
||||
usr_jb_current_time.month,
|
||||
usr_jb_current_time.day,
|
||||
usr_jb_current_time.hour,
|
||||
usr_jb_current_time.min,
|
||||
usr_jb_current_time.sec);*/
|
||||
}
|
||||
}
|
||||
|
||||
struct sys_time usr_set_time;
|
||||
void usr_set_sys_time()//设置时间
|
||||
{
|
||||
//dev_ioctl(__this->dev_handle, IOCTL_SET_SYS_TIME, (u32)&usr_set_time);
|
||||
write_sys_time(&usr_set_time);
|
||||
usr_jb_current_time.year=usr_set_time.year;
|
||||
usr_jb_current_time.month=usr_set_time.month;
|
||||
usr_jb_current_time.day=usr_set_time.day;
|
||||
usr_jb_current_time.hour=usr_set_time.hour;
|
||||
usr_jb_current_time.min=usr_set_time.min;
|
||||
usr_jb_current_time.sec=usr_set_time.sec;
|
||||
|
||||
usr_var.usr_cureent_utc=convertToUtcTimestamp(usr_jb_current_time.year,usr_jb_current_time.month,usr_jb_current_time.day,usr_jb_current_time.hour,usr_jb_current_time.min,usr_jb_current_time.sec);
|
||||
if(usr_var.usr_cureent_utc)
|
||||
{
|
||||
if(usr_var.usr_cureent_utc>usr_var.usr_timezoneOffset)usr_var.usr_cureent_utc=usr_var.usr_cureent_utc-usr_var.usr_timezoneOffset;
|
||||
}
|
||||
printf("##### usr_var.usr_cureent_utc = %d\n",usr_var.usr_cureent_utc);
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
void app_rtc_task()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "asm/pwm_led.h"
|
||||
#include "tone_player.h"
|
||||
#include "ui_manage.h"
|
||||
#include "app_main.h"
|
||||
#include "app_task.h"
|
||||
#include "asm/charge.h"
|
||||
#include "app_power_manage.h"
|
||||
#include "app_charge.h"
|
||||
#include "user_cfg.h"
|
||||
#include "audio.h"
|
||||
#include "vm.h"
|
||||
#include "sys_time.h"
|
||||
|
||||
/*
|
||||
硬件定时器demo
|
||||
*/
|
||||
|
||||
|
||||
extern const int CONFIG_CPU_UNMASK_IRQ_ENABLE;//需要极准确的定时效果时开启不可屏蔽中断
|
||||
static JL_TIMER_TypeDef *TIMER = NULL;
|
||||
static int irq_id = -1;
|
||||
#define TIMER_UNIT_US 1000//设置中断时间,单位us
|
||||
#define MAX_TIME_CNT 0x7fff //分频准确范围,更具实际情况调整
|
||||
#define MIN_TIME_CNT 0x0030
|
||||
static const u16 timer_div[] = {
|
||||
/*0000*/ 1,
|
||||
/*0001*/ 4,
|
||||
/*0010*/ 16,
|
||||
/*0011*/ 64,
|
||||
/*0100*/ 2,
|
||||
/*0101*/ 8,
|
||||
/*0110*/ 32,
|
||||
/*0111*/ 128,
|
||||
/*1000*/ 256,
|
||||
/*1001*/ 4 * 256,
|
||||
/*1010*/ 16 * 256,
|
||||
/*1011*/ 64 * 256,
|
||||
/*1100*/ 2 * 256,
|
||||
/*1101*/ 8 * 256,
|
||||
/*1110*/ 32 * 256,
|
||||
/*1111*/ 128 * 256,
|
||||
};
|
||||
|
||||
|
||||
SET_INTERRUPT
|
||||
static void user_timer_isr()
|
||||
{
|
||||
/*if(CONFIG_CPU_UNMASK_IRQ_ENABLE){
|
||||
unmask_enter_critical();
|
||||
}
|
||||
else{
|
||||
local_irq_disable();
|
||||
}*/
|
||||
TIMER->CON |= BIT(14); //清中断标志位
|
||||
//用户自定义代码
|
||||
//......
|
||||
|
||||
|
||||
/*if(CONFIG_CPU_UNMASK_IRQ_ENABLE){
|
||||
unmask_exit_critical();
|
||||
}
|
||||
else{
|
||||
local_irq_enable();
|
||||
}*/
|
||||
}
|
||||
|
||||
int user_timer_uninit();
|
||||
int user_timer_init(u16 usr_time_us)
|
||||
{
|
||||
u32 prd_cnt;
|
||||
u8 index;
|
||||
u32 app_timer_clk = 24000000;//时钟用STD24M
|
||||
|
||||
user_timer_uninit();
|
||||
|
||||
printf("------------%s :%d", __func__, __LINE__);
|
||||
printf("%d %d %d %d %d %d\n", JL_TIMER0->CON, JL_TIMER1->CON, JL_TIMER2->CON,
|
||||
JL_TIMER3->CON, JL_TIMER4->CON, JL_TIMER5->CON);
|
||||
|
||||
/*if((JL_TIMER0->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER0;
|
||||
irq_id = IRQ_TIME0_IDX;
|
||||
}
|
||||
else */if((JL_TIMER1->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER1;
|
||||
irq_id = IRQ_TIME1_IDX;
|
||||
}
|
||||
else if((JL_TIMER2->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER2;
|
||||
irq_id = IRQ_TIME2_IDX;
|
||||
}
|
||||
else if((JL_TIMER3->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER3;
|
||||
irq_id = IRQ_TIME3_IDX;
|
||||
}
|
||||
else if((JL_TIMER4->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER4;
|
||||
irq_id = IRQ_TIME4_IDX;
|
||||
}
|
||||
else if((JL_TIMER5->CON & 0x3) == 0) {
|
||||
TIMER = JL_TIMER5;
|
||||
irq_id = IRQ_TIME5_IDX;
|
||||
}
|
||||
else{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) {
|
||||
prd_cnt = usr_time_us * (app_timer_clk / 1000000) / timer_div[index];
|
||||
if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("irq_id %d PRD : 0x%x / %d", irq_id, prd_cnt, app_timer_clk);
|
||||
|
||||
TIMER->CNT = 0;
|
||||
TIMER->PRD = prd_cnt - 1;
|
||||
request_irq(irq_id, 2, user_timer_isr, 0);
|
||||
if(CONFIG_CPU_UNMASK_IRQ_ENABLE){
|
||||
irq_unmask_set(irq_id, 1, 0);
|
||||
}
|
||||
TIMER->CON = (index << 4) | BIT(0) | BIT(11)| BIT(12);//BIT(11)| BIT(12):时钟用STD24M
|
||||
|
||||
printf("PRD : 0x%x / %d", prd_cnt, app_timer_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_timer_uninit()
|
||||
{
|
||||
if(TIMER == NULL){
|
||||
return 0;
|
||||
}
|
||||
TIMER->CON = BIT(14);
|
||||
unrequest_irq(irq_id);
|
||||
TIMER = NULL;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "system/includes.h"
|
||||
#include "asm/uart_dev.h"
|
||||
#include "system/event.h"
|
||||
#include "key_event_deal.h"
|
||||
#include "app_task.h"
|
||||
|
||||
#include "usr_jb_global.h"
|
||||
|
||||
|
||||
/*
|
||||
硬件uart demo
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if USR_JB_UART_RX_PIN
|
||||
|
||||
|
||||
/*
|
||||
在打开sleep时使用UART接收,需要把UART RX引脚配置为唤醒脚
|
||||
在休眠时,如果对端MCU需要发数据给蓝牙IC,则需要先发一个唤醒帧来唤醒蓝牙IC,
|
||||
唤醒后对端MCU再发送协议数据,具体用法全局搜索 USR_JB_UART_RX_PIN 这个宏,本demo已经做好了
|
||||
|
||||
或者也可以单独使用一个GPIO,当对端有数据要过来时,拉低或者拉高GPIO,数据结束后再休眠
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
const uart_bus_t *uart_bus;
|
||||
static u8 uart_cbuf[512] __attribute__((aligned(4)));
|
||||
static u8 uart_rxbuf[512] __attribute__((aligned(4)));
|
||||
|
||||
|
||||
int uart_tr_send_data(u8 *data, u32 len)
|
||||
{
|
||||
if(uart_bus)
|
||||
{
|
||||
if(usr_var.usr_uart_recieve==0)
|
||||
{
|
||||
usr_var.usr_uart_recieve=1;
|
||||
uart_bus->write(data,len);
|
||||
usr_var.usr_uart_recieve=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_bus->write(data,len);
|
||||
}
|
||||
}
|
||||
}
|
||||
void usr_uart_send_test()
|
||||
{
|
||||
char* test_string="I am uart test\n";
|
||||
uart_tr_send_data(test_string,strlen(test_string));
|
||||
}
|
||||
static void uart_u_task(void *arg)
|
||||
{
|
||||
int ret;
|
||||
u32 uart_rxcnt = 0;
|
||||
printf("uart_u_task start\n");
|
||||
while (1)
|
||||
{
|
||||
//uart_bus->read()在尚未收到串口数据时会pend信号量,挂起task,直到UART_RX_PND或UART_RX_OT_PND中断发生,post信号量,唤醒task
|
||||
uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
|
||||
if (uart_rxcnt)
|
||||
{
|
||||
usr_var.usr_uart_recieve=5;///不进入sleep
|
||||
uart_tr_send_data(uart_rxbuf,uart_rxcnt);///收发回传测试
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uart_dev_init_main()
|
||||
{
|
||||
|
||||
struct uart_platform_data_t u_arg = {0};
|
||||
u_arg.tx_pin = USR_JB_UART_TX_PIN;
|
||||
u_arg.rx_pin = USR_JB_UART_RX_PIN;
|
||||
u_arg.rx_cbuf = uart_cbuf;
|
||||
u_arg.rx_cbuf_size = 512;
|
||||
u_arg.frame_length = 512;
|
||||
u_arg.rx_timeout = 10;
|
||||
u_arg.isr_cbfun = NULL;
|
||||
u_arg.baud = 115200;
|
||||
u_arg.is_9bit = 0;
|
||||
|
||||
uart_bus = uart_dev_open(&u_arg);
|
||||
if (uart_bus != NULL)
|
||||
{
|
||||
printf("uart_dev_open() success\n");
|
||||
os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user