Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите модифицировать стандартную библиотеку.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
zheka
Господа, есть у меня девайс, одним из элементов которого является интерфейс к LCD на KS0066. Устройство спаяно, все ОК. Да вот беда - выгорел выход PC4. Других контроллеров у меня нет, в tqfp корпусе в Воронеже не найти, только под заказ. А времени нет. У меня один выход - перепаять PC4 на PC3 и модифицировать программу.

В COdeVision есть стандартная библиотека под LCD, она отправляет команды через старшие 4 бита PORTC. Значит нужно сдвинуть 4 бит на место третьего. Делаю это так:
Код
a |= (a & 0x10)>>1


То есть каждую посылку нужно обрабатывать таким образом.
ОДнако при редактировании библиотеки возникли непонятки.
В фунцию передается параметр data, однако внутри функции к этому параметру обращения нет:
CODE
void _lcd_write_data(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf0 | (1<<__lcd_rs) | (1<<__lcd_rd) | (1<<__lcd_enable);set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
#endasm
_lcd_write_nibble(); //RD=0, write MSN
#asm
ld r26,y
swap r26
#endasm
_lcd_write_nibble(); //write LSN
#asm
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}



Вот вся библиотека. Как ее отредактировать?

CODE
/* LCD driver routines

CodeVisionAVR C Compiler
© 1998-2007 Pavel Haiduc, HP InfoTech S.R.L.
*/

#asm
.equ __lcd_direction=__lcd_port-1
.equ __lcd_pin=__lcd_port-2
.equ __lcd_rs=0
.equ __lcd_rd=1
.equ __lcd_enable=2
.equ __lcd_busy_flag=7
#endasm

#pragma used+
static unsigned char _base_y[4]={0x80,0xc0};
unsigned char _lcd_x,_lcd_y,_lcd_maxx;
#pragma used-

static void _lcd_delay(void)
{
#asm
ldi r31,15
__lcd_delay0:
dec r31
brne __lcd_delay0
#endasm
}

void _lcd_ready(void)
{
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
cbi __lcd_port,__lcd_rs ;RS=0
__lcd_busy:
#endasm
_lcd_delay();
#asm
sbi __lcd_port,__lcd_enable;EN=1
#endasm
_lcd_delay();
#asm
in r26,__lcd_pin
cbi __lcd_port,__lcd_enable;EN=0
#endasm
_lcd_delay();
#asm
sbi __lcd_port,__lcd_enable;EN=1
#endasm
_lcd_delay();
#asm
cbi __lcd_port,__lcd_enable;EN=0
sbrc r26,__lcd_busy_flag
rjmp __lcd_busy
#endasm
}

static void _lcd_write_nibble(void)
{
#asm
andi r26,0xf0
or r26,r27
out __lcd_port,r26 ;write
sbi __lcd_port,__lcd_enable;EN=1
#endasm
_lcd_delay();
#asm
cbi __lcd_port,__lcd_enable;EN=0
#endasm
_lcd_delay();
}

void _lcd_write_data(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf0 | (1<<__lcd_rs) | (1<<__lcd_rd) | (1<<__lcd_enable);set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
#endasm
_lcd_write_nibble(); //RD=0, write MSN
#asm
ld r26,y
swap r26
#endasm
_lcd_write_nibble(); //write LSN
#asm
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

/* write a byte to the LCD character generator or display RAM */
void lcd_write_byte(unsigned char addr, unsigned char data)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
_lcd_write_data(data);
}

static void _lcd_read_nibble(void)
{
#asm
sbi __lcd_port,__lcd_enable;EN=1
#endasm
_lcd_delay();
#asm
in r30,__lcd_pin ;read
cbi __lcd_port,__lcd_enable;EN=0
#endasm
_lcd_delay();
#asm
andi r30,0xf0
#endasm
}

static unsigned char lcd_read_byte0(void)
{
_lcd_delay();
_lcd_read_nibble(); // read MSN
#asm
mov r26,r30
#endasm
_lcd_read_nibble(); // read LSN
#asm
cbi __lcd_port,__lcd_rd ;RD=0
swap r30
or r30,r26
#endasm
}

/* read a byte from the LCD character generator or display RAM */
unsigned char lcd_read_byte(unsigned char addr)
{
_lcd_ready();
_lcd_write_data(addr);
_lcd_ready();
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rs ;RS=1
#endasm
return lcd_read_byte0();
}

/* set the LCD display position x=0..39 y=0..3 */
void lcd_gotoxy(unsigned char x, unsigned char y)
{
_lcd_ready(); // RS=0
_lcd_write_data(_base_y[y]+x);
_lcd_x=x;
_lcd_y=y;
}

// clear the LCD
void lcd_clear(void)
{
_lcd_ready(); // RS=0
_lcd_write_data(2); // cursor home
_lcd_ready();
_lcd_write_data(0xc); // cursor off
_lcd_ready();
_lcd_write_data(1); // clear
_lcd_x=_lcd_y=0;
}

void lcd_putchar(char c)
{
#asm
push r30
push r31
ld r26,y
set
cpi r26,10
breq __lcd_putchar1
clt
#endasm
++_lcd_x;
if (_lcd_x>_lcd_maxx)
{
#asm("__lcd_putchar1:")
++_lcd_y;
lcd_gotoxy(0,_lcd_y);
#asm("brts __lcd_putchar0")
};
#asm
rcall __lcd_ready
sbi __lcd_port,__lcd_rs;RS=1
ld r26,y
st -y,r26
rcall __lcd_write_data
__lcd_putchar0:
pop r31
pop r30
#endasm
}

// write the string str located in SRAM to the LCD
void lcd_puts(char *str)
{
char k;
while (k=*str++) lcd_putchar(k);
}

// write the string str located in FLASH to the LCD
void lcd_putsf(char flash *str)
{
char k;
while (k=*str++) lcd_putchar(k);
}

static void _long_delay(void)
{
#asm
clr r26
clr r27
__long_delay0:
sbiw r26,1 ;2 cycles
brne __long_delay0;2 cycles
#endasm
}

static void _lcd_init_write(unsigned char data)
{
#asm
cbi __lcd_port,__lcd_rd ;RD=0
in r26,__lcd_direction
ori r26,0xf7 ;set as output
out __lcd_direction,r26
in r27,__lcd_port
andi r27,0xf
ld r26,y
#endasm
_lcd_write_nibble(); //RD=0, write MSN
#asm
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
}

// initialize the LCD controller
unsigned char lcd_init(unsigned char lcd_columns)
{
#asm
cbi __lcd_port,__lcd_enable;EN=0
cbi __lcd_port,__lcd_rs ;RS=0
#endasm
_lcd_maxx=lcd_columns;
_base_y[2]=lcd_columns+0x80;
_base_y[3]=lcd_columns+0xc0;
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x30);
_long_delay();
_lcd_init_write(0x20);
_long_delay();
_lcd_write_data(0x28);
_long_delay();
_lcd_write_data(4);
_long_delay();
_lcd_write_data(0x85);
_long_delay();
#asm
in r26,__lcd_direction
andi r26,0xf ;set as input
out __lcd_direction,r26
sbi __lcd_port,__lcd_rd ;RD=1
#endasm
if (lcd_read_byte0()!=5) return 0;
_lcd_ready();
_lcd_write_data(6);
lcd_clear();
return 1;
}
ARV
скачайте отсюда библиотечку, из нее выдерите модуль lcd.c и хидер lcd.h. в последнем элементарно осуществляется произвольное распределение пинов по портам - т.е. предлагаю отказаться от CVAVR-овской либы.
zheka
Скачал, но там под winavr - я дольше переделывать буду. Нельзя ли совет по первоначально поставленнной задаче?
oll
Цитата(zheka @ Nov 27 2009, 01:03) *
однако внутри функции к этому параметру обращения нет

как нет? - ld r26,y
дальше написать на ассемблере сдвижку бита
а хватит ли ножек порта?
Вам нужно 4 бита для ног управления __lcd_rs, __lcd_rd, __lcd_enable, __lcd_busy_flag
и 4 бита данных - один сгорел
Выход - оду ногу управления перенести на другой порт (библиотеку Кодевижена придется править конкретно)
или как подсказал ARV использовать стороннюю бтблиотеку.

Нашел - пользовал в Кодевижн, будут свободные ноги (доработать напильником biggrin.gif ):
CODE
#define LCD_E_SET PORTC.5=1
#define LCD_E_CLR PORTC.5=0
#define LCD_RS_SET PORTC.4=1
#define LCD_RS_CLR PORTC.4=0

#define WASTE waste_lcd()
#define DELAY for (del = 0; del < 16; del++)

long del;

void waste_lcd(void)
{
}

void LCD4_WR4bits(unsigned char c)
{
c &= 0x0F;
// c = c << 4;
LCD_E_SET;
WASTE;
PORTD &= 0xF0;
PORTD |= c;
WASTE;
LCD_E_CLR;
WASTE;
}

void LCD4_Init(void)
{
delay_ms(15); // Wait on power up 15mS
LCD_RS_CLR;
DELAY;

LCD4_WR4bits( 0x03); // Function Set 8bit
delay_ms(5);

LCD4_WR4bits( 0x03); // Function Set 8bit
delay_ms(5);

LCD4_WR4bits( 0x03); // Function Set 8bit
delay_ms(5);

LCD4_WR4bits( 0x02); // Function Set 4bit
delay_ms(5);

LCD4_WR4bits( 0x02); // Function Set
LCD4_WR4bits( 0x08);
DELAY;

LCD4_WR4bits( 0x00); // Display ON/OFF
LCD4_WR4bits( 0x0C); // Display ON, Curson OFF, Blink OFF
DELAY;

LCD4_WR4bits( 0x00); // Entry mode
LCD4_WR4bits( 0x06);
DELAY;

LCD_RS_SET;
delay_ms(5);
}

void LCD4_Clear(void)
{
LCD_RS_CLR;
DELAY;
LCD4_WR4bits( 0x00); // Clear Display
LCD4_WR4bits( 0x01);
DELAY;
LCD_RS_SET;
delay_ms(5);
}

void LCD4_Home(void)
{
LCD_RS_CLR;
DELAY;
LCD4_WR4bits( 0x00);
LCD4_WR4bits( 0x02);
DELAY;
LCD_RS_SET;
delay_ms(5);
}

void LCD4_Home2(void)
{
LCD_RS_CLR;
DELAY;
LCD4_WR4bits( 0x0C); // Clear Display
LCD4_WR4bits( 0x00);
DELAY;
LCD_RS_SET;
delay_ms(5);
}



void LCD4_PutC(unsigned char data)
{
LCD4_WR4bits( data >> 4);
DELAY;
LCD4_WR4bits( data);
DELAY;
}

void LCD4_PutS_RAM(unsigned char *data)
{
unsigned char c = 0;

while (data[c] != 0) {
LCD4_WR4bits( data[c] >> 4);
LCD4_WR4bits( data[c++]);
DELAY;
}
}

void LCD4_PutS(flash unsigned char *data)
{
unsigned char c = 0;

while (data[c] != 0) {
LCD4_WR4bits( data[c] >> 4);
LCD4_WR4bits( data[c++]);
DELAY;
}
}


использовать так:
CODE
LCD4_Home(); // 1:st row
LCD4_PutS("..OLL 2006©..");
LCD4_Home2(); // 2:nd row
LCD4_PutS("Version 1.0");
delay_ms(1000);

........
Value=read_adc(0);
itoa(Value,str_buffer);
LCD4_Clear();
LCD4_Home();
LCD4_PutS("U=");
LCD4_PutS_RAM(str_buffer);
.......
zheka
Непонятнейшим образом, но ножка 4 заработала.Почему она не работала не знаю, непропай исключаю - ибо измерял на самой ноге, а не дорожке. Замыкание исключаю, так как если бы с соедних ног на нее поступал сигнал, это было бы видно.
В общем безо всякой правки все работает. Спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.