还是之前折腾GD32L233时弄的一块SLCD屏,改吧改吧就在AT32F425上跑起来了。
板子其实比较简单,打板如下:
SLCD板
其中:
信号管脚RC参数中的R参数以及VLCD的分压电阻可直接参考手册。
裸屏是交流信号驱动,直接用DC是不行的,得用交流测试。
用一段线缠绕在交流线上面,就可以测试了。
SLCD裸屏测试
测试结果
SLCD参数
其中最关键的驱动条件参数,一般而言:
SLCD COM和SEG
SLCD按duty的周期执行扫描模式,所以简单的理解:
假如我们需要显示第一位的数字为2,那么对应的【8】,其中:标号2,标号3,标号4,标号6,标号7会亮。
参考SEG图,我们知道:
要想把标号2,标号3,标号4,标号6,标号7点亮,那么:
就是下表:
COM0 | COM1 | COM2 | COM3 | |
---|---|---|---|---|
SEG9 | 1 | 1 | 1 | 0 |
SEG10 | 0 | 0 | 1 | 1 |
也就是往这两个地址写入0xE和0x3就能显示数字2。
懂了啵?!
只说跟STM32、GD32的差异性吧。
是定义了2个宏定义。
GPIO_DRIVE_STRENGTH_STRONGER = 0x01, /*!< stronger sourcing/sinking strength */
GPIO_DRIVE_STRENGTH_MODERATE = 0x02 /*!< moderate sourcing/sinking strength */
又单独给每个管脚定义了SOURCE,封装起来又多了一个函数。
GPIO的封装接口:
static gpio_pins_source_type get_gpio_pins_source(uint32_t pin)
{
switch (pin)
{
case GPIO_PINS_0:
return GPIO_PINS_SOURCE0;
case GPIO_PINS_1:
return GPIO_PINS_SOURCE1;
case GPIO_PINS_2:
return GPIO_PINS_SOURCE2;
case GPIO_PINS_3:
return GPIO_PINS_SOURCE3;
case GPIO_PINS_4:
return GPIO_PINS_SOURCE4;
case GPIO_PINS_5:
return GPIO_PINS_SOURCE5;
case GPIO_PINS_6:
return GPIO_PINS_SOURCE6;
case GPIO_PINS_7:
return GPIO_PINS_SOURCE7;
case GPIO_PINS_8:
return GPIO_PINS_SOURCE8;
case GPIO_PINS_9:
return GPIO_PINS_SOURCE9;
case GPIO_PINS_10:
return GPIO_PINS_SOURCE10;
case GPIO_PINS_11:
return GPIO_PINS_SOURCE11;
case GPIO_PINS_12:
return GPIO_PINS_SOURCE12;
case GPIO_PINS_13:
return GPIO_PINS_SOURCE13;
case GPIO_PINS_14:
return GPIO_PINS_SOURCE14;
case GPIO_PINS_15:
return GPIO_PINS_SOURCE15;
default:
return GPIO_PINS_SOURCE0;
}
}
void gpio_init_af_mode(crm_periph_clock_type rcu, gpio_type * gpio, uint32_t pin, uint32_t speed, uint32_t af_func)
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(rcu, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = (gpio_drive_type)speed;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pins = pin;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(gpio, &gpio_init_struct);
gpio_pin_mux_config(gpio, get_gpio_pins_source(pin), (gpio_mux_sel_type)af_func);
}
void gpio_init_output_mode(crm_periph_clock_type rcu, gpio_type * gpio, uint32_t pin, uint32_t speed, uint8_t set)
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(rcu, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = (gpio_drive_type)speed;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = pin;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(gpio, &gpio_init_struct);
if (set)
{
gpio_bits_set(gpio, pin);
}
else
{
gpio_bits_reset(gpio, pin);
}
}
一堆寄存器配置,参见芯片手册。
偷个懒,一把贴出来了。
【说明】SLCD切换的时序很短,延时直接用计数--就好。
这个代码跟GD32L233的代码几乎一致,只是定义的管脚和接口宏定义变了,这就是架构提前设计好的好处。
//#define SLCD_USING_SPI
#if defined(SPI1_FOR_SLCD)
/* SPI1:PB13-SCK-SPI_SCK PB14-CE-SPI_MISO PB15-DATA-SPI_MOSI */
#define CURRENT_SPI SPI1
#define CURRENT_SPI_RCU RCU_SPI1
#define SLCD_RCU CRM_GPIOB_PERIPH_CLOCK
#define SLCD_GPIO GPIOB
#define SLCD_WR_CLK_PIN GPIO_PINS_13
#define SLCD_CS_PIN GPIO_PINS_14
#define SLCD_DATA_PIN GPIO_PINS_15
#ifdef SLCD_USING_SPI
#else
#define CS_HIGH gpio_bits_set(SLCD_GPIO, SLCD_CS_PIN);
#define CS_LOW gpio_bits_reset(SLCD_GPIO, SLCD_CS_PIN);
#define WR_CLK_HIGH gpio_bits_set(SLCD_GPIO, SLCD_WR_CLK_PIN);
#define WR_CLK_LOW gpio_bits_reset(SLCD_GPIO, SLCD_WR_CLK_PIN);
#define DATA_HIGH gpio_bits_set(SLCD_GPIO, SLCD_DATA_PIN);
#define DATA_LOW gpio_bits_reset(SLCD_GPIO, SLCD_DATA_PIN);
#define DATA gpio_input_data_bit_read(SLCD_GPIO, SLCD_DATA_PIN)
#endif
// SLCD命令码
#define CTRL_CMD 0x80 //写控制命令
#define DATA_CMD 0xA0 //写数据命令
#define LCD_ON 0x06 //打开LCD 1000 0000 011x
#define LCD_OFF 0x04 //关闭LCD 1000 0000 010x
#define SYS_EN 0x02 //系统振荡器开 1000 0000 001x
#define RC_OSC 0x30 //内部RC振荡器(上电默认256K) 1000 0011 0XXX
#define COM_BIAS 0x52 //4COM,1/3bias 1000 010 10X1X
#define SLCD_OFF send_cmd_slcd(LCD_OFF)
#define SLCD_ON send_cmd_slcd(LCD_ON)
#define SLCD_SYS_EN send_cmd_slcd(SYS_EN)
#define SLCD_RC_OSC send_cmd_slcd(RC_OSC)
#define SLCD_COM_BIAS send_cmd_slcd(COM_BIAS)
//,C,c,d,E,F,H,h,L,n,N,o,P,r,t,U,-, ,*/
//,,0x1D,0x0E,0x6E,0x1F,0x17,0x67,0x47,0x0D,0x46,0x75,0x37,
#define DISP_0 0xD7
#define DISP_1 0x06
#define DISP_2 0xE3
#define DISP_3 0xA7
#define DISP_4 0x36
#define DISP_5 0xB5
#define DISP_6 0xF5
#define DISP_7 0x07
#define DISP_8 0xF7
#define DISP_9 0xB7
#define DISP_A 0x77
#define DISP_B 0xF7
#define DISP_b 0xF4
#define DISP_C 0xD1
#define DISP_D 0xD7
#define DISP_c 0xE0
#define DISP_d 0xE6
#define DISP_E 0xF1
#define DISP_F 0x71
#define DISP_H 0x76
#define DISP_h 0x74
#define DISP_L 0xD0
#define DISP_n 0x64
#define DISP_N 0x57
#define DISP_o 0xE4
#define DISP_P 0x73
#define DISP_r 0x60
#define DISP_t 0xF0
#define DISP_U 0xD6
#define DISP__ 0x20
#define DISP_EMPTY 0x00
void spi5_init(){}
#ifdef SLCD_USING_SPI
void spi1_init()
{
}
#else
void spi1_init() {
gpio_init_output_mode(SLCD_RCU, SLCD_GPIO, SLCD_WR_CLK_PIN, GPIO_DRIVE_STRENGTH_MODERATE, 0);
gpio_init_output_mode(SLCD_RCU, SLCD_GPIO, SLCD_CS_PIN, GPIO_DRIVE_STRENGTH_MODERATE, 0);
gpio_init_output_mode(SLCD_RCU, SLCD_GPIO, SLCD_DATA_PIN, GPIO_DRIVE_STRENGTH_STRONGER, 0);
}
static void slcd_delay(int count) {
while (count) {
count--;
}
}
void send_bit_slcd(uint8_t sdat, uint8_t cnt)
{
//data 的高cnt位写入,高位在前
uint8_t i;
for(i = 0; i < cnt; i++)
{
WR_CLK_LOW;
slcd_delay(20);
if(sdat&0x80)
{
DATA_HIGH;
}
else
{
DATA_LOW;
}
slcd_delay(20);
WR_CLK_HIGH;
slcd_delay(20);
sdat<<=1;
}
slcd_delay(20);
}
void send_cmd_slcd(uint8_t command)
{
//发送指令
CS_LOW;
send_bit_slcd(CTRL_CMD, 4); //写入标志码b100
send_bit_slcd(command, 8); //没有最高位为1的命令,直接将command的最高位写0
CS_HIGH;
}
void write_slcd(uint8_t addr, uint8_t sdat)
{
addr<<=2;
CS_LOW;
send_bit_slcd(DATA_CMD, 3); //写入标志码b101
send_bit_slcd(addr, 6); //写入addr 的高6位
send_bit_slcd(sdat, 8); //写入data 的8位
CS_HIGH;
}
void slcd_user_init(void)
{
SLCD_OFF;
SLCD_SYS_EN;
SLCD_RC_OSC;
SLCD_COM_BIAS;
SLCD_ON;
slcd_display_data(DISP_0,DISP_0,DISP_0,DISP_0,DISP_0,DISP_0);delay_ms(600);
slcd_display_data(DISP_1,DISP_1,DISP_1,DISP_1,DISP_1,DISP_1);delay_ms(600);
slcd_display_data(DISP_2,DISP_2,DISP_2,DISP_2,DISP_2,DISP_2);delay_ms(600);
slcd_display_data(DISP_3,DISP_3,DISP_3,DISP_3,DISP_3,DISP_3);delay_ms(600);
slcd_display_data(DISP_4,DISP_4,DISP_4,DISP_4,DISP_4,DISP_4);delay_ms(600);
slcd_display_data(DISP_5,DISP_5,DISP_5,DISP_5,DISP_5,DISP_5);delay_ms(600);
slcd_display_data(DISP_6,DISP_6,DISP_6,DISP_6,DISP_6,DISP_6);delay_ms(600);
slcd_display_data(DISP_7,DISP_7,DISP_7,DISP_7,DISP_7,DISP_7);delay_ms(600);
slcd_display_data(DISP_8,DISP_8,DISP_8,DISP_8,DISP_8,DISP_8);delay_ms(600);
slcd_display_data(DISP_9,DISP_9,DISP_9,DISP_9,DISP_9,DISP_9);delay_ms(600);
slcd_display_data(DISP__,DISP__,DISP__,DISP__,DISP__,DISP__);delay_ms(600);
slcd_display_data(DISP_H,DISP_E,DISP_L,DISP_L,DISP_0,DISP_EMPTY);
}
void slcd_display_data(uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4, uint8_t data5, uint8_t data6)
{
uint8_t addr = 9;
write_slcd(addr, data1);
addr += 2;
write_slcd(addr, data2);
addr += 2;
write_slcd(addr, data3);
addr += 2;
write_slcd(addr, data4);
addr += 2;
write_slcd(addr, data5);
addr += 2;
write_slcd(addr, data6);
addr += 2;
}
#endif
#endif