1.15. Segment Code LCD

本芯片内置一个断码屏驱动器,最大支持4*27 或 6*25的LCD断码屏 支持1/2、1/3、1/4bias; 支持电压灵活调节; 支持跳秒信号映射到任意的seg口; 可使用RTC晶振32KHz或内部LRC作为模块时钟; 详细的示例代码请参考SDK “cpu/demo/segment_code_lcd_demo.c”。

Note

  1. 使用RTC晶振32KHz为模块时钟时,才支持跳秒设置

  2. 晶振需要初始化RTC后才能使用(占用PA7 PA8)

1.15.1. 断码屏驱动使用流程

Note

  1. LCD IO复用其他功能时,LCD的COM口需要保持高阻状态

  2. LCD IO驱动过程中,会翻转,因此其他功能复用需要考虑协议相互干扰

1.15.1.1. LCD IO不复用

  1. 配置使用到的LCD COM和SEG IO高阻输入,且DIE=0 DIEH=0;

  2. 配置LCD显示像素点寄存器;

  3. 配置LCD模式配置;

  4. LCD配置成连续推屏模式;

  5. 开启LCD使能位;

  6. 写入软件KIST START BIT(KST);

  7. LCD模块开始工作,接管IO;

1.15.1.2. LCD IO复用切换

  1. LCD配置成断续推屏模式;

  2. 等待LCD当前帧结束pending或者中断;

  3. 关闭LCD模块使能位;

  4. LCD模块停止工作,COM IO保持高阻输入;

  5. SEG IO可释放,复用做其他功能;

  6. 其他功能完成后,恢复SEG IO为高阻输入,继续推屏;

  7. 开启LCD模块使能位;

  8. 写入软件KIST START BIT(KST);

  9. LCD模块开始工作,接管IO,下一步到(2)

1.15.1.3. LCD IO不复用切换

  1. LCD配置成断续推屏模式

  2. 等待LCD当前帧结束pending或者中断

  3. 关闭LCD模块使能位

  4. LCD模块停止工作,COM IO保持高阻输入

  5. SEG IO可释放,复用做其他功能

  6. 其他功能完成后,恢复SEG IO为高阻输入

  7. LCD配置成连续推屏模式

  8. 开启LCD模块使能位

  9. 写入软件KIST START BIT(KST)

  10. LCD模块开始工作,接管IO

1.15.2. 断码屏驱动基本接口

1.15.2.1. segment_code_lcd_init

lcd断码屏驱动初始化接口,支持配置时钟,电压,充电模式,跳秒等,先初始化之后才能调用其他api

原型:

struct segment_code_lcd_platform_data {
    enum lcd_clk clk;               //时钟配置
    enum lcdcp_pmup_vol chgpump_vol;//charge pump电压配置
    enum lcdcp_ldob_vol ldob_vol;   //ldob电压配置
    enum lcd_vol vlcd;              //电压分压设置
    enum lcd_bias bias;             //偏压设置
    enum lcd_chgmode chgmode;       //充电模式设置
    u8   chgduty;                   //强充时间设置,当chgmode==LCD_CHGMODE_MANY_CYCLE时有效
    enum lcd_com_index dot_com;     //跳秒脚对应的com口(使用OSL_CLK时钟时才有效)
    enum lcd_seg_index dot_seg;     //跳秒脚对应的seg口(使用OSL_CLK时钟时才有效)
    u8   lcd_com_en;                //设置使用的com的IO, bit0~bit5 对应 com0~com5
    u32  lcd_seg_en;                //设置使用的seg的IO, bit0~bit26 对应 seg0~seg26
    u8   ctu_en;                    //1:连续模式(CPU控制) 0:断续模式(ie=1)
    void (*isr_cb)(void);           //断续模式时,中断回调函数
};

void segment_code_lcd_init(const struct segment_code_lcd_platform_data *lcd_dat);
参数:

lcd_dat

初始化配置传参

返回值

1.15.2.2. segment_code_lcd_deinit

关闭LCD断码屏模块,与segment_code_lcd_init相对

原型:

void segment_code_lcd_deinit(void);
参数:

参数

返回值

1.15.2.3. segment_code_lcd_set_ctu_en

设置LCD驱动为连续模式还是断续模式,中途改变LCD驱动方式时可调用

原型:

void segment_code_lcd_set_ctu_en(u8 ctu_en);
参数:

ctu_en

0:断续模式 1:连续模式(CPU控制)

返回值

1.15.2.4. segment_code_lcd_set_dot_en

设置跳秒使能/禁能,跳秒显示切换时调用

原型:

void segment_code_lcd_set_dot_en(u8 dot_en);
参数:

dot_en

0:跳秒禁能 1:跳秒使能

返回值

1.15.2.5. segment_code_lcd_start

启动LCD模块,当使用断续推屏模式时,复用功能完成后,调用该接口重新启动推屏

原型:

void segment_code_lcd_start(void);
参数:

传参

返回值

1.15.2.6. segment_code_lcd_fill_point

需要填充一个点或者清除一个点时调用,该接口不会更新到硬件寄存器

原型:

void segment_code_lcd_fill_point(u8 icon, u8 isfill);
参数:

icon

点的位置, 高5位表示seg口,低3bit表示com口

isfill

0:清除 1:填充

返回值

1.15.2.7. segment_code_lcd_fill_number

填充一个数字,需要填充数字时调用,该接口不会更新到硬件寄存器

原型:

void segment_code_lcd_fill_number(const u8 ptr[], u8 num);
参数:

ptr[]

需要显示数字的7段LCD对应的点位置的数组

num

需要填充的数字,num > 11时清除显示

返回值

1.15.2.8. segment_code_lcd_fill_char

填充一个英文字符,需要填充英文字符时调用,该接口不会更新到硬件寄存器

原型:

void segment_code_lcd_fill_char(const u8 ptr[], u8 cc);
参数:

ptr[]

需要显示英文字符的7段LCD对应的点位置的数组

cc

需要填充的英文字符, ‘a’~’z’ 或 ‘A’~’Z’

返回值

1.15.2.9. segment_code_lcd_disp_clear

清屏,需要清屏时调用,该接口不会更新到硬件寄存器

原型:

void segment_code_lcd_disp_clear(void);
参数:

传参

返回值

1.15.2.10. segment_code_lcd_disp_all

全显,需要全显时调用,该接口不会更新到硬件寄存器

原型:

void segment_code_lcd_disp_all(void);
参数:

传参

返回值

1.15.2.11. segment_code_lcd_disp_update

更新显示缓存,需要把缓存更新到寄存器时调用

原型:

void segment_code_lcd_disp_update(void);
参数:

传参

返回值

1.15.3. HADC使用示例代码

#define  NUM_SYS_HUN_A    (LCD_POINT(0, 9))
#define  NUM_SYS_HUN_B    (LCD_POINT(0, 8))
#define  NUM_SYS_HUN_C    (LCD_POINT(2, 8))
#define  NUM_SYS_HUN_D    (LCD_POINT(2, 9))
#define  NUM_SYS_HUN_E    (LCD_POINT(1, 9))
#define  NUM_SYS_HUN_F    (LCD_POINT(INVALID_COM, 0))
#define  NUM_SYS_HUN_G    (LCD_POINT(1, 8))

#define  NUM_SYS_TEN_A    (LCD_POINT(0, 6))
#define  NUM_SYS_TEN_B    (LCD_POINT(1, 5))
#define  NUM_SYS_TEN_C    (LCD_POINT(2, 5))
#define  NUM_SYS_TEN_D    (LCD_POINT(2, 6))
#define  NUM_SYS_TEN_E    (LCD_POINT(2, 7))
#define  NUM_SYS_TEN_F    (LCD_POINT(1, 7))
#define  NUM_SYS_TEN_G    (LCD_POINT(1, 6))

#define  NUM_SYS_ONE_A    (LCD_POINT(0, 3))
#define  NUM_SYS_ONE_B    (LCD_POINT(1, 2))
#define  NUM_SYS_ONE_C    (LCD_POINT(2, 2))
#define  NUM_SYS_ONE_D    (LCD_POINT(2, 3))
#define  NUM_SYS_ONE_E    (LCD_POINT(2, 4))
#define  NUM_SYS_ONE_F    (LCD_POINT(1, 4))
#define  NUM_SYS_ONE_G    (LCD_POINT(1, 3))

#define  NUM_DIA_HUN_A    (LCD_POINT(3, 9))
#define  NUM_DIA_HUN_B    (LCD_POINT(3, 8))
#define  NUM_DIA_HUN_C    (LCD_POINT(5, 8))
#define  NUM_DIA_HUN_D    (LCD_POINT(5, 9))
#define  NUM_DIA_HUN_E    (LCD_POINT(4, 9))
#define  NUM_DIA_HUN_F    (LCD_POINT(INVALID_COM, 0))
#define  NUM_DIA_HUN_G    (LCD_POINT(4, 8))

#define  NUM_DIA_TEN_A    (LCD_POINT(3, 6))
#define  NUM_DIA_TEN_B    (LCD_POINT(3, 5))
#define  NUM_DIA_TEN_C    (LCD_POINT(4, 5))
#define  NUM_DIA_TEN_D    (LCD_POINT(5, 6))
#define  NUM_DIA_TEN_E    (LCD_POINT(4, 7))
#define  NUM_DIA_TEN_F    (LCD_POINT(3, 7))
#define  NUM_DIA_TEN_G    (LCD_POINT(4, 6))

#define  NUM_DIA_ONE_A    (LCD_POINT(3, 3))
#define  NUM_DIA_ONE_B    (LCD_POINT(3, 2))
#define  NUM_DIA_ONE_C    (LCD_POINT(4, 2))
#define  NUM_DIA_ONE_D    (LCD_POINT(5, 3))
#define  NUM_DIA_ONE_E    (LCD_POINT(4, 4))
#define  NUM_DIA_ONE_F    (LCD_POINT(3, 4))
#define  NUM_DIA_ONE_G    (LCD_POINT(4, 3))

static const u8 NUM_SYS_HUN[7] = {NUM_SYS_HUN_A, NUM_SYS_HUN_B, NUM_SYS_HUN_C, NUM_SYS_HUN_D, NUM_SYS_HUN_E, NUM_SYS_HUN_F, NUM_SYS_HUN_G};
static const u8 NUM_SYS_TEN[7] = {NUM_SYS_TEN_A, NUM_SYS_TEN_B, NUM_SYS_TEN_C, NUM_SYS_TEN_D, NUM_SYS_TEN_E, NUM_SYS_TEN_F, NUM_SYS_TEN_G};
static const u8 NUM_SYS_ONE[7] = {NUM_SYS_ONE_A, NUM_SYS_ONE_B, NUM_SYS_ONE_C, NUM_SYS_ONE_D, NUM_SYS_ONE_E, NUM_SYS_ONE_F, NUM_SYS_ONE_G};

static const u8 NUM_DIA_HUN[7] = {NUM_DIA_HUN_A, NUM_DIA_HUN_B, NUM_DIA_HUN_C, NUM_DIA_HUN_D, NUM_DIA_HUN_E, NUM_DIA_HUN_F, NUM_DIA_HUN_G};
static const u8 NUM_DIA_TEN[7] = {NUM_DIA_TEN_A, NUM_DIA_TEN_B, NUM_DIA_TEN_C, NUM_DIA_TEN_D, NUM_DIA_TEN_E, NUM_DIA_TEN_F, NUM_DIA_TEN_G};
static const u8 NUM_DIA_ONE[7] = {NUM_DIA_ONE_A, NUM_DIA_ONE_B, NUM_DIA_ONE_C, NUM_DIA_ONE_D, NUM_DIA_ONE_E, NUM_DIA_ONE_F, NUM_DIA_ONE_G};

const struct segment_code_lcd_platform_data lcd_test_data = {
    .clk = LCD_CLK_SEL_WCLK,
    .chgpump_vol = LCDCP_PUMPVOL_SEL_3P8V,
    .ldob_vol = LCDCP_LDOB_SEL_3P3V,
    .vlcd = LCD_VOL_SEL_1P000XLCDCP,
    .bias = LCD_BIAS_1DIV3,
    .chgmode = LCD_CHGMODE_STRONG,
    .chgduty = 0,
    .dot_com = LCD_COM0,
    .dot_seg = LCD_SEG18,
    .lcd_com_en = 0x3F,     //6com
    .lcd_seg_en = 0x7FFFFC, //21seg
    .ctu_en = 1, //0:断续推屏(en ie) 1:连续推屏
    .isr_cb = NULL,
};

void segment_code_lcd_test(void)
{
    segment_code_lcd_init(&lcd_test_data);

    segment_code_lcd_disp_all();
    segment_code_lcd_disp_update();
    mdelay(500);

    segment_code_lcd_disp_clear();

    segment_code_lcd_fill_number(NUM_SYS_HUN, 1);
    segment_code_lcd_fill_number(NUM_SYS_TEN, 2);
    segment_code_lcd_fill_number(NUM_SYS_ONE, 3);

    segment_code_lcd_fill_number(NUM_DIA_HUN, 1);
    segment_code_lcd_fill_number(NUM_DIA_TEN, 5);
    segment_code_lcd_fill_number(NUM_DIA_ONE, 7);

    segment_code_lcd_disp_update();

    while (1) {
        wdt_clear();
    }
}