|
注册登录,了解更多芯片技术。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
一、概述
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灯数据BUFstatic 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 = (u8)rand(); } u16 again_cnt = 0; while (1) { wdt_clear(); for (u8 i = 0; i < sizeof(ledc_test_buf); i++) { ledc_test_buf = (u8)rand(); } ledc_send_rgbbuf(ledc_test_buf, sizeof(ledc_test_buf), again_cnt); delay_10ms(10); } }#endif
|
|