WH1602B запущен на STM32

Переделал без использования библиотеки stm32f10x_gpio.h. Вместо 4 битной шины использую 8 битную, так проще. Ни как не могу запонить #if #endif, там что добавляйте если это надо.
Теперь нормально запускается.


#include "stm32f10x.h"
#include "lcd.h"


int main(void)
{
	lcd_init();
	lcd_goto(0,0);
	lcd_write_str("строка 1");
	lcd_goto(1,0);
	lcd_write_str("строка 2");
    while(1)
    {

    }
}



#include "stm32f10x.h"
#include "sys_init.h"

/************************************************/
/**Пины управления использутся в старших разряжах регистра порта ввода/вывода, тоесть от 8..15****/
/**Для выбор пинов управления номера в значения инициализации портов MODEx, CNFx, ODRx, x = 8-15.*/
#define LCD_PORT 		GPIOC              /*Выбор порта для подключения дисплея******************/
#define LCD_PORT_RCC 	RCC_APB2ENR_IOPCEN /*Вкл. тактирование порта для подключения дисплея******/

#define RS_MODE	GPIO_CRH_MODE10
#define RW_MODE	GPIO_CRH_MODE9
#define E_MODE	GPIO_CRH_MODE8
#define CNF_RS  GPIO_CRH_CNF10
#define CNF_RW  GPIO_CRH_CNF9
#define CNF_E   GPIO_CRH_CNF8
#define Rab_RS  GPIO_ODR_ODR10
#define Rab_RW  GPIO_ODR_ODR9
#define Rab_E   GPIO_ODR_ODR8
/******************************************************************************/
/*Дисплей подключается к младшим регистрам порта вводы/вывода (LCD_PORT) 0...7*/
/* DB0	= GPIO_ODR_ODR0 */
/* DB1	= GPIO_ODR_ODR1 */
/* DB2	= GPIO_ODR_ODR2 */
/* DB3	= GPIO_ODR_ODR3 */
/* DB4	= GPIO_ODR_ODR4 */
/* DB5	= GPIO_ODR_ODR5 */
/* DB6	= GPIO_ODR_ODR6 */
/* DB7	= GPIO_ODR_ODR7 */
/*******************************************************************************/
/*Распиновка дисплея*/
/* GND  1*/
/* +5V  2*/
/* Vo   3*/
/* RS   4*/
/* RW   5*/
/* E    6*/
/* DB0	7*/
/* DB1	8*/
/* DB2  9*/
/* DB3	10*/
/* DB4	11*/
/* DB5	12*/
/* DB6	13*/
/* DB7  14*/
/* +4.2 15 LED*/
/* k 16 16*/

#define E1   LCD_PORT->ODR |= Rab_E
#define E0   LCD_PORT->ODR &=~Rab_E
#define RW1  LCD_PORT->ODR |= Rab_RW
#define RW0  LCD_PORT->ODR &=~Rab_RW
#define RS1  LCD_PORT->ODR |= Rab_RS
#define RS0  LCD_PORT->ODR &=~Rab_RS

void init_gpio_out(void);
void init_gpio_in(void);
void lcd_wait(void);
void lcd_write_cmd(unsigned char cmd);
void lcd_write_dat(unsigned char dat);
void lcd_init(void);
void lcd_goto(uc8 x,uc8 y);
void lcd_write_str(uc8 *STRING);




#include "lcd.h"
const unsigned char russian[]={ 0x41, 0xA0, 0x42, 0xA1, 0xE0, 0x45,
0xA3, 0xA4, 0xA5,0xA6, 0x4B, 0xA7, 0x4D, 0x48, 0x4F, 0xA8, 0x50,0x43,
0x54, 0xA9, 0xAA, 0x58, 0xE1, 0xAB, 0xAC, 0xE2, 0xAD,0xAE, 0x62,
0xAF, 0xB0, 0xB1, 0x61, 0xB2, 0xB3, 0xB4, 0xE3, 0x65, 0xB6, 0xB7,
0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0x6F, 0xBE, 0x70, 0x63,0xBF,
0x79, 0xE4, 0x78, 0xE5, 0xC0, 0xC1, 0xE6, 0xC2,0xC3, 0xC4, 0xC5,
0xC6, 0xC7 };

void init_gpio_out(void)
{
	RCC->APB2ENR |= LCD_PORT_RCC;
	LCD_PORT->CRL |= GPIO_CRL_MODE ;//выход, максимальная скорость переключения — 50 мГц
	LCD_PORT->CRL &=~ GPIO_CRL_CNF ;//двухтактный выход общего назначения

	LCD_PORT->CRH |=  RW_MODE;
	LCD_PORT->CRH |=  E_MODE ;
	LCD_PORT->CRH |=  RS_MODE;
	LCD_PORT->CRH &=~ CNF_RW;
	LCD_PORT->CRH &=~ CNF_E;
	LCD_PORT->CRH &=~ CNF_RS;
}


void init_gpio_in(void)//цифровой вход с подтягивающим резистором
{
	RCC->APB2ENR |=  LCD_PORT_RCC;
	LCD_PORT->CRL &=~ GPIO_CRL_MODE;//вывод сконфигурирован как вход;
	LCD_PORT->CRL |=  0x88888888;//цифровой вход с подтягивающим резистором

}

void lcd_wait(void)
{
init_gpio_in();
RS0;
RW1;
E1;
Delay_us(450);
E0;
while(LCD_PORT->IDR & GPIO_IDR_IDR7 )
	{
	}
init_gpio_out();
}
void lcd_write_cmd(unsigned char cmd)
{
	LCD_PORT->BRR = 0x00FF;
	lcd_wait();
	RS0;RW0;
	E1;
	LCD_PORT->ODR |= cmd &0x00FF;
	Delay_us(450);
	E0;
}
void lcd_write_dat(unsigned char dat)
{
	LCD_PORT->BRR = 0x00FF;
	lcd_wait();
	RS1;
	RW0;
	E1;
	LCD_PORT->ODR |= dat &0x00FF;
	Delay_us(450);
	E0;

}
void lcd_write_str(uc8 *STRING)
{
	char c; //символ из строки
	while (c=*STRING++){
	if(c>=192) lcd_write_dat(russian[c-192]);
	else lcd_write_dat(C);
	}
}

/*Положеня курсора
 * x = 0 - первая строка
 * x = 1 - вторая строка
 * y = 0...16*/
void lcd_goto(uc8 x,uc8 y)
{
	int str;
	str = y + 0x80;
	if(x == 1)
	{
	str+= 0x40;
	}
	lcd_write_cmd(str);
}
void lcd_init(void)
{
	init_gpio_out();
	Delay_ms(30);
	lcd_write_cmd(0b00111100);/*2 строки, дисплей выкл.*/
	Delay_us(40);
	lcd_write_cmd(0b00001111);/*дисплей вкл, курсор выкл, миг.курсор выкл.*/
	Delay_us(40);
	lcd_write_cmd(0b00000001);/*Очистить дисплей*/
	Delay_ms(2);
	lcd_write_cmd(0b00000110);/*Инкремент адреса, экран не движется*/
}

Комментарии (23)

RSS свернуть / развернуть
А почему бы lcd_goto не написать как-то так:

str = 0x80 + x * 0x40 + y;

аппаратное умножение в SMT32 есть.
0
  • avatar
  • Telek
  • 26 октября 2011, 10:03
Аппаратное умножение не надо, можно обойтись сдвигом:
str = 0x80 + (x << 6) + y;

На самом деле, между Вашим и моим кодом нет разницы, вменяемый компилятор всё равно будет использовать сдвиг.
А что будет в коде автора, когда вдруг y будет больше 15?
0
Хе-хе, а у нас с вами почти одинаково :D
void LCD_Goto(unsigned char line, unsigned char pos)
{
LCDCmd((line <<6) | pos | 0x80);
}
Ну а автору конечно поработать надо, над техникой )
0
Еще можно добавить русский:
const unsigned char russian[]={ 0x41, 0xA0, 0x42, 0xA1, 0xE0, 0x45,
0xA3, 0xA4, 0xA5,0xA6, 0x4B, 0xA7, 0x4D, 0x48, 0x4F, 0xA8, 0x50,0x43,
0x54, 0xA9, 0xAA, 0x58, 0xE1, 0xAB, 0xAC, 0xE2, 0xAD,0xAE, 0x62, 
0xAF, 0xB0, 0xB1, 0x61, 0xB2, 0xB3, 0xB4, 0xE3, 0x65, 0xB6, 0xB7, 
0xB8, 0xB9, xBA, 0xBB, 0xBC, 0xBD, 0x6F, 0xBE, 0x70, 0x63,0xBF, 
0x79, 0xE4, 0x78, 0xE5, 0xC0, 0xC1, 0xE6, 0xC2,0xC3, 0xC4, 0xC5, 
0xC6, 0xC7 };

static void write_data(uint8_t data)
{
    uint8_t c;
    c = data;
    if ( c > 191 ) c = russian[c - 192];    
    PIN_ON(OLED_2X16_RS); 
    write_4bit(c);
    write_4bit((uint8_t) (c << 4));
}

Ожидание готовности дисплея:
static void wait_ready(void)
{
    PIN_OFF(OLED_2X16_RS); 
    PIN_CONFIGURATION(OLED_2X16_DB7_IN);
    PIN_CONFIGURATION(OLED_2X16_DB6_IN);
    PIN_CONFIGURATION(OLED_2X16_DB5_IN);
    PIN_CONFIGURATION(OLED_2X16_DB4_IN); 
    PIN_ON(OLED_2X16_RW); 
    while((read_4bit() & 0x80) != 0x00)
    {
        read_4bit();
    } 
    read_4bit(); 
    PIN_OFF(OLED_2X16_RW); 
    PIN_CONFIGURATION(OLED_2X16_DB7);
    PIN_CONFIGURATION(OLED_2X16_DB6);
    PIN_CONFIGURATION(OLED_2X16_DB5);
    PIN_CONFIGURATION(OLED_2X16_DB4);
} 

Ну и, как правильно подметили выше, более короткую функцию установки курсора:
void set_cursor_position(uint8_t row, uint8_t colum)
{
    write_instruction((uint8_t) (0x80 | (row > 0 ? 0x40 : 0) | colum));
}
Или можно вообще макросом:
#define LCD_Goto(x,y) LCD_WriteCom(((((y)& 1)*0x40)+((x)& 7))|128) 
0
str = y + 0x80;
if(x == 1)
{
str+= 0x40;
}

end!!!
0
  • avatar
  • wowa
  • 26 октября 2011, 10:34
Зачем делать ветвления там, где можно без них? Хоть тут быстродействие не особо критично, все же как-то неприятно на душе ))
0
Да я что-то долго писал ответ :) Пока его написал — уже несколько раз успели ответить… Вобщем после компиляции практически небудет разницы и код с переходом может работать и быстрей.
0
Спасибо за ваши варианты Lcd_goto, разберусь как они работают и поменяю свою функцию.
За русский тоже спасибо!
0
А у них же FSMC есть, или я опять что-то упустил в жизни?
0
Тока в стоногих.
0
Точно, у них же ноги мельче. Глянул мельком, показалось что корпус 64 ногий.
0
тыкайте в кокосе обновить Repository
Залил туда свой main.c ;-)комменты на русском только слились, ну это херня я думаю. Тем более что этот код мало кому нужен.
0
Русская кодировка сдвинута относительно cp1251 (ну та которая в маздае?)
Значить считываем видовый русский символ и сдвигаем его в минус на… какое-то число.
0
заработал WG12864B, осталось допилить до нормального состояние. Строки там выводить и.т.д.
0
Привет! Всё работает супер, спасибо!
Однако попробовал поменять порт на GPIOB (также пробовал GPIOA) с помошью правки дефайнов и не получилось. В чём грабли?

#define port GPIOB // вместо GPIOC, я выбрал GPIOB с его PBxx пинами платы STM32VL-DISCOVERY
#define init_port RCC_APB2Periph_GPIOB // тут поменял последнюю буковку C на B
#define pin_e GPIO_Pin_3 // и эти пины переназначил PB3…
#define pin_rw GPIO_Pin_4 // PB4
#define pin_rs GPIO_Pin_5 // и PB5

#define lcd_shift 11 // последним получается пин PB11
#define use_gpio GPIO_Pin_14 // а первым PB14

опробованые пины 5В толерантны

Спасибо!
0
PB3 — JTDO
PB4 — NJTRST
0
Хорошо, а можно поподобней? Чтоб знать где в даташите смотреть какие пины нельзя использовать или как переконфигурить и чем это грозит? Спасибо!
0
Я сам и отвечу, тогда. В даташите есть колонка Main Function (After reset). Вот там и прописана основная функция после старта контроллера. В моём случае надо было найти чтобы функция соответствовала имени пина на плате. Я выбрал:
#define pin_e GPIO_Pin_7
#define pin_rw GPIO_Pin_8
#define pin_rs GPIO_Pin_9
и взял разъём на 4 пина, пропустив Boot пустой дыркой.
0
Почему после рестррта кнопкой на VLDiscovery инициализация дисплея такова, что всё отобрадается только в верхней строке. То есть, будто он не инициализируется. Если перезапустить сбросом питания, то стартует нормально.
0
скорей всего мой косячный код
0
решил переделать и немного задержку подправил, вроде стабильно работает. Но теперь 8 бит и пины данных не поменяешь.
0
А как вы делали ф-цию задержки Delay_us?
0
у кого-то спёр, не помню у кого.Суть деления частоны на 1 с много нулями и умножением на ms или us
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.