-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
一、概述
AD16支持一路硬件LEDC对灯带进行驱动和控制,LEDC通过DMA数据传输,可通过配置可以使led灯带显示不同颜色变化。在使用之前需要将JL_LEDCK->CLK寄存器的[1-0]置0,然后在进行相关配置。否则可能出现异常。
二、示例驱动代码
typedef enum { //由48M时钟源算出的时间单位
t_21ns,
t_42ns,
t_63ns,
t_125ns,
t_250ns,
t_500ns,
t_1us,
t_2us,
t_4us,
} t_unit_enum;
struct ledc_platform_data {
u8 port; //输出引脚
u8 idle_level; //当前帧的空闲电平,0:低电平, 1:高电平
u8 out_inv; //起始电平,0:高电平开始, 1:低电平开始
u8 bit_inv; //取数据时高低位镜像,0:不镜像,1:8位镜像,2:16位镜像,3:32位镜像
t_unit_enum t_unit; //时间单位
u8 t1h_cnt; //1码的高电平时间 = t1h_cnt * t_unit;
u8 t1l_cnt; //1码的低电平时间 = t1l_cnt * t_unit;
u8 t0h_cnt; //0码的高电平时间 = t0h_cnt * t_unit;
u8 t0l_cnt; //0码的低电平时间 = t0l_cnt * t_unit;
u32 t_rest_cnt; //复位信号时间 = t_rest_cnt * t_unit;
void (*cbfun)(void);//中断回调函数
};
#define LEDC_PLATFORM_DATA_BEGIN(data) \
const struct ledc_platform_data data = {
#define LEDC_PLATFORM_DATA_END() \
};
static void (*ledc_isr_cbfun)(void) = NULL;
volatile u8 ledc_busy = 0;
___interrupt
void ledc_isr(void)
{
if (JL_LEDC->CON & BIT(7)) { //PND
JL_LEDC->CON |= BIT(6); //CPND
if (ledc_isr_cbfun) {
ledc_isr_cbfun();
}
}
ledc_busy = 0;
}
static u8 t_div[9] = {1, 2, 3, 6, 12, 24, 48, 96, 192};
void ledc_init(const struct ledc_platform_data *arg)
{
gpio_set_die(arg->port, 1);
gpio_set_direction(arg->port, 0);
gpio_set_pull_up(arg->port, 0);
gpio_set_pull_down(arg->port, 0);
gpio_och_sel_output_signal(arg->port, OUTPUT_CH_SIGNAL_GP_LEDC); //OUTPUT_CHANNEL自动分配
//std_48M
JL_LEDCK->CLK &= ~(0b11 << 0);
JL_LEDCK->CLK |= (0b10 << 0);
//set div
JL_LEDCK->CLK &= ~(0xff << 8);
JL_LEDCK->CLK |= ((t_div[arg->t_unit] - 1) << 8);
JL_LEDC->CON = BIT(6); //CPND
if (arg->cbfun) { //异步工作方式,建议用于传输数据量较大的应用
JL_LEDC->CON |= BIT(5); //IE
request_irq(IRQ_LEDC_IDX, IRQ_LEDC_IP, ledc_isr, 0);
ledc_isr_cbfun = arg->cbfun;
}
if (arg->idle_level) {
JL_LEDC->CON |= BIT(4);
}
if (arg->out_inv) {
JL_LEDC->CON |= BIT(3);
}
JL_LEDC->CON |= (arg->bit_inv << 1);
/**********配置信号高低电平时间*******/
JL_LEDC->TIX = 0;
JL_LEDC->TIX |= ((arg->t1h_cnt - 1) << 24); //输出1码高电平时间,单位CNT_CK,实际值减1
JL_LEDC->TIX |= ((arg->t1l_cnt - 1) << 16); //输出1码低电平时间,单位CNT_CK,实际值减1
JL_LEDC->TIX |= ((arg->t0h_cnt - 1) << 8); //输出0码高电平时间,单位CNT_CK,实际值减1
JL_LEDC->TIX |= ((arg->t0l_cnt - 1) << 0); //输出0码低电平时间,单位CNT_CK,实际值减1
/************************************/
JL_LEDC->RSTX = 0;
JL_LEDC->RSTX |= (arg->t_rest_cnt << 8); //每一帧开始复位有效时间长度,单位CNT_CK
log_info("JL_LEDCK->CLK = 0x%x\n", JL_LEDCK->CLK);
log_info("JL_LEDC->CON = 0x%x\n", JL_LEDC->CON);
log_info("JL_LEDC->TIX = 0x%x\n", JL_LEDC->TIX);
log_info("JL_LEDC->RSTX = 0x%x\n", JL_LEDC->RSTX);
}
void ledc_send_rgbbuf(u8 *rgbbuf, u32 buf_len, u16 again_cnt)
{
if (JL_LEDC->CON & BIT(5)) { //用于异步工作方式,防止数据重入
while (ledc_busy);
}
JL_LEDC->ADR = (u32)rgbbuf;
JL_LEDC->FD = buf_len * 8; //FD_LEN RGB灯配置为灯数量n*3*8,即为不重复n个LED数据循环
JL_LEDC->LP = again_cnt; //FD_LEN重复次数,即将JL_LEDC->FD的数据在一次循环中重复发送,0则不重复
ledc_busy = 1; //防止打断上一次发送的数据,用于异步工作方式
JL_LEDC->CON |= BIT(0); //启动
if (!(JL_LEDC->CON & BIT(5))) { //用于同步工作方式(无中断),建议用于发送数据量较少的应用
while (!(JL_LEDC->CON & BIT(7)));
JL_LEDC->CON |= BIT(6);
}
}
#if 0
// *INDENT-OFF*
/******************************* 参考示例 ***********************************/
#define LED_NUM 10
static u8 ledc_test_buf[LED_NUM * 3] __attribute__((aligned(4))); //RGB灯数据BUF
static void ledc_callback()
{
putchar('c');
}
LEDC_PLATFORM_DATA_BEGIN(ledc0_data)
.port = IO_PORTA_04,
.idle_level = 0,
.out_inv = 0,
.bit_inv = 1,
.t_unit = t_42ns,
.t1h_cnt = 24,
.t1l_cnt = 7,
.t0h_cnt = 7,
.t0l_cnt = 24,
.t_rest_cnt = 200,
.cbfun = ledc_callback,
LEDC_PLATFORM_DATA_END()
void delay_10ms(u32 tick);
void wdt_clear(void);
void ledc_test(void)
{
log_info("************* ledc test **************\n");
ledc_init(&ledc0_data);
/* ledc_test_buf[0] = 0; */
/* ledc_test_buf[1] = 85; */
/* ledc_test_buf[2] = 170; */
for (u8 i = 0; i < sizeof(ledc_test_buf); i++) {
ledc_test_buf[i] = (u8)rand();
}
u16 again_cnt = 0;
while (1) {
wdt_clear();
for (u8 i = 0; i < sizeof(ledc_test_buf); i++) {
ledc_test_buf[i] = (u8)rand();
}
ledc_send_rgbbuf(ledc_test_buf, sizeof(ledc_test_buf), again_cnt);
delay_10ms(10);
}
}
#endif
Metadata
Metadata
Assignees
Labels
No labels