prst 0 30 января, 2011 Опубликовано 30 января, 2011 (изменено) · Жалоба Запускаю на своем модуле ARM7MODA LCD индикатор из серии KS0066. Режим этот нужен, так что вопрос принципиальный. Уже столько камней об него заточено что и писать нет смысла, однако есть какие то грабли при запуске, и я вот не пойму то ли это у него не так что то то ли я жутко торможу, надеюсь что первое. Жутко принципиальный момент, по этому хочется его запустить. Итак, 8bit mode - запустился на раз плюнуть, код я подставил свой старый, уже рабочий. Но был затык, и как оказалось, выяснил опытным путем, что индикатор мне попался жуткий тормозяра... каких я не встречал до этого. Индикатор NEWTEC NC08082A. Ну то ладно, главное что нашел виновника, это - его медлительность. Потом залез в его даташит, там приведены намного меньшие таймауты необходимые для работы... А по моему коду получается что нужно намного большие временные периоды между RS -> E -> Data. А вот 4bit mode - напрочь не хочет заводиться. И вот тут у меня какой то шоковый ступор. Так как 4 бит я уже запускал несколько штук ранее. А на этом индикаторе - не получается. В общем вот я вам и пишу, взгляните на код и скажите, это я где то торможу или для этого индикатора нужно что-то отличное от даташита... На не оптимизированный код в 4bit mode не обращайте внимания, это я уже ради удобства выснения проблемы все перенес в один фрагмент #define _RS _B8 #define _E _B9 #define LCD_TIME_FAST (10) #define LCD_TIME_SLOW (50) #define LCD_TIME LCD_TIME_SLOW ... ... //----------------------------------------------------------- void LCD_Config(void) { #ifdef LCD_4_BITS AT91PS_SYS regs = AT91C_BASE_SYS; tick(600*LCD_TIME); regs->PIOA_ODSR &=~_RS; // RS=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x20); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x80); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x00); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x80); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x00); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x10); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x00); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (0x30); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; delay(); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_RS; // RS=0; #endif /*LCD_4_BITS*/ #ifdef LCD_8_BITS unsigned char i=0, init_value[] = { 0x01, 0x02, 0x06, 0x0c, 0x14, 0x38 }; /* 16x2 */ for (i=0; i<sizeof(init_value); i++) { lcd_cmd ( init_value[i] ); } #endif /*LCD_8_BITS*/ } /* LCD_Config() */ //----------------------------------------------------------- void lcd_cmd (unsigned char ch) { AT91PS_SYS regs = AT91C_BASE_SYS; #ifdef LCD_4_BITS udelay(); tick(600*LCD_TIME); regs->PIOA_ODSR &=~_RS;// RS=0; tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (ch&0xf0); tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; udelay(); tick(60*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(60*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |= (ch&0x0f)<<4; tick(60*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; tick(60*LCD_TIME); regs->PIOA_ODSR &=~_RS; // RS=0; #endif /*LCD_4_BITS*/ #ifdef LCD_8_BITS tick(600*LCD_TIME); regs->PIOA_ODSR &=~_RS;// RS=0; tick(6*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(6*LCD_TIME); regs->PIOA_ODSR &= 0xffffff00; tick(6*LCD_TIME); regs->PIOA_ODSR |= ch; tick(6*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; tick(6*LCD_TIME); regs->PIOA_ODSR &=~_RS; // RS=0; #endif /*LCD_8_BITS*/ } /* lcd_cmd() */ //----------------------------------------------------------- // Set address of first byte on desired row void lcd_xy( unsigned char y, unsigned char x ) { unsigned char LCD_ROW_ADDRESS[4] = { 0x00, 0x40, 0x14, 0x54 }; unsigned char AddrXYData; AT91PS_SYS regs = AT91C_BASE_SYS; AddrXYData = LCD_ROW_ADDRESS[y]+x; #ifdef LCD_4_BITS tick(60*LCD_TIME); regs->PIOA_ODSR &=~_RS; // RS=0; tick(40*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(40*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |=0x80|(AddrXYData&0xF0); tick(40*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; tick(40*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(40*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |=(AddrXYData&0x0F)<<4; tick(40*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; #endif /*LCD_4_BITS*/ #ifdef LCD_8_BITS tick(6*LCD_TIME); regs->PIOA_ODSR &=~_RS;// RS=0; tick(4*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(4*LCD_TIME); regs->PIOA_ODSR &= 0xffffff00; tick(1); regs->PIOA_ODSR |=(0x80|AddrXYData); tick(4*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; #endif /*LCD_8_BITS*/ } /* lcd_xy() */ //----------------------------------------------------------- /* Show message on LCD*/ void lcd_char( unsigned char value ) { AT91PS_SYS regs = AT91C_BASE_SYS; unsigned char kod; kod = value; kod = lcd_recode( value ); #ifdef LCD_4_BITS tick(30*LCD_TIME); regs->PIOA_ODSR |=_RS; // RS=1; tick(30*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(20*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |=((kod &0xF0)); tick(20*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; tick(30*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(20*LCD_TIME); regs->PIOA_ODSR &= 0xffffff0f; tick(1); regs->PIOA_ODSR |=((kod &0x0F)<<4); tick(20*LCD_TIME); regs->PIOA_ODSR &=~_E; // E=0; #endif /*LCD_4_BITS*/ #ifdef LCD_8_BITS tick(3*LCD_TIME); regs->PIOA_ODSR |=_RS; // RS=1; tick(3*LCD_TIME); regs->PIOA_ODSR |=_E; // E=1; tick(2*LCD_TIME); regs->PIOA_ODSR &= 0xffffff00; tick(1); regs->PIOA_ODSR |= kod; tick(2*LCD_TIME); regs->PIOA_ODSR &= ~_E; // E=0; #endif /*LCD_8_BITS*/ } /* lcd_char() */ ... ... ...тормознутость можете сами заметить по 60*LCD_TIME Вопрос - Где же что не правильно? Или есть такое что индикатор не поддерживает этот режим? Так должен - даташит обещает... Изменено 31 января, 2011 пользователем IgorKossak Пользуйтесь тэгами [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 30 января, 2011 Опубликовано 30 января, 2011 · Жалоба Боже ж мой! Да подключите вы PCF8575 к аппаратному I2C МК, а к ней в свою очередь этот ваш символьный LCD и используйте на здоровье любимый вами 8-ми битный режим вместо этого "ногодрыжества". Ногодрыжество на ARM это совершенно специальный вид секса с элементами грубого мазохизма ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 30 января, 2011 Опубликовано 30 января, 2011 · Жалоба Код, уж простите, просто чудовищный. И это еще самый мягкий эпитет, который к нему можно применить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
izerg 9 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба Rezident, а чем ногодрыжество через PCF8575 в программе будет принципиально отличатся от простого ногодрыжества? Да еще и в используемой плате, где стоит AT91SAM7S с его "фирменным" i2c. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба Тем более, что программа пишется один раз, ногами дрыгает не юзер, а контроллер (ему не надоест), а вот тратиться на PCF8575 абсолютно в каждый экземпляр устройства таки придётся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба Да, читать такой код сложновато. Если правильно понял, то в первых трех обращениях надо не regs->PIOA_ODSR |= (0); (что само по себе бессмысленно), а regs->PIOA_ODSR |= (0x30); И вообще, если уж идти таким путем: uint32_t Temp = regs->PIOA_OWSR; regs->PIOA_OWER = 0xF0; regs->PIOA_OWDR = ~0xF0; regs->PIOA_SODR = _E; // E = 1 regs->PIOA_ODSR = 0x30; regs->PIOA_CODR = _E; // E = 0 .... .... regs->PIOA_OWDR = 0xF0; regs->PIOA_OWER = Temp; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба Rezident, а чем ногодрыжество через PCF8575 в программе будет принципиально отличатся от простого ногодрыжества?Принципиально? - ничем. И там и там ногодрыжество. Однако ТС по какой-то причине экономит выводы МК, выделенные для подключения LCD-модуля. Вот я и предлагаю ему расширить их количество. Тем более, что с 8-ми битным подключением у него LCD работает (по его словам). Да еще и в используемой плате, где стоит AT91SAM7S с его "фирменным" i2c.А что, там багов немеряно? У LPC17хх и LPC11xx подключение I2C никаких проблем не вызывало. :cranky: Хотя оно и понятно - все же родное Филипсовское. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
izerg 9 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба А что, там багов немеряно? Почему немеряно, очень даже меряно: Раз. Два Причем LPC17хх и LPC11xx? Зачем человеку по лишним граблям ходить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prst 0 31 января, 2011 Опубликовано 31 января, 2011 · Жалоба Код, уж простите, просто чудовищный. И это еще самый мягкий эпитет, который к нему можно применить. да я знаю, вы меня не задели )) я этот код вообще не причесывал, и развернул специально что бы не перепрыгивать между листингами и функциями. Это только на стадию запуска 4 битного режима. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 1 февраля, 2011 Опубликовано 1 февраля, 2011 · Жалоба Вот что у меня работает на SAM7S32 в четырёхбитной позе. Задержки для MCK=55МГц ; ; lcd HD44780 support routines ; INCLUDE common.inc LCD_RS_LINE EQU 0x00000004 LCD_E_LINE EQU 0x00000008 AREA TEXT, CODE, READONLY ARM ; задержка примерно на 350 нс lcdDelayE ldr r10, =4 lcdDelayE_loop subs r10, r10, #1 bne lcdDelayE_loop bx LR ; задержка примерно на 40 мкс lcdDelay50us ldr r10, =280 b lcdDelayE_loop ; задержка примерно на 250 мкс lcdDelay250us ldr r10, =1750 b lcdDelayE_loop EXPORT lcdDelay2500us ; задержка примерно на 2500 мкс lcdDelay2500us ldr r10, =17000 b lcdDelayE_loop EXPORT delay2500us delay2500us stmfd SP!, {r10, LR} bl lcdDelay2500us ldmfd SP!, {r10, PC} ; отправить команду в LCD ; IN ; r9 - байт команды lcdSendCommand stmfd SP!, {r9,r10,LR} ; ставим признак команды str r5, [r7, #PIO_CODR] ; задержка bl lcdDelayE ; дёргаем линией Е str r6, [r7, #PIO_SODR] ;bl lcdDelayE ; выставляем старшую половину байта str r9, [r7, #PIO_ODSR] bl lcdDelayE ; str r6, [r7, #PIO_CODR] ;bl lcdDelayE bl lcdDelayE lcdSend4BitsBackdoor ; дёргаем линией Е str r6, [r7, #PIO_SODR] ;bl lcdDelayE ; выставляем вторую половину байта mov r10, r9, lsl #4 str r10, [r7, #PIO_ODSR] bl lcdDelayE ; str r6, [r7, #PIO_CODR] bl lcdDelay50us ; на выход ldmfd SP!, {r9,r10,PC} ; отправить 4 бита команды в LCD ; IN ; r9 - 4 бита команды lcdSendCommandHalf stmfd SP!, {r9,r10,LR} ; ставим признак команды str r5, [r7, #PIO_CODR] b lcdSend4BitsBackdoor ; отправить байт данных в LCD ; IN ; r9 - байт данных lcdSendData str LR, [sP, #-4]! ; ставим признак данных str r5, [r7, #PIO_SODR] ; задержка bl lcdDelayE ; дёргаем линией Е str r6, [r7, #PIO_SODR] ;bl lcdDelayE ; выставляем старшую половину байта str r9, [r7, #PIO_ODSR] bl lcdDelayE ; str r6, [r7, #PIO_CODR] ;bl lcdDelayE bl lcdDelayE ; дёргаем линией Е str r6, [r7, #PIO_SODR] ;bl lcdDelayE ; выставляем вторую половину байта mov r10, r9, lsl #4 str r10, [r7, #PIO_ODSR] bl lcdDelayE ; str r6, [r7, #PIO_CODR] bl lcdDelay50us ; на выход ldr PC, [sP], #4 ; инициализация LCD lcdFirstInit stmfd SP!, {r0,r5-r7,r9,r10,LR} ldr r7, =PIO_BASE ; set lines PA4-PA7 for parallel output ldr r5, =0x000000F0 str r5, [r7, #PIO_OWER] add r5, #0x0C str r5, [r7, #PIO_CODR] str r5, [r7, #PIO_OER] ldr r5, =LCD_RS_LINE ldr r6, =LCD_E_LINE ; delay ldr r0, =12 lcdFirstInit_delay bl lcdDelay2500us subs r0, #1 bne lcdFirstInit_delay ; 3 команды инициализации ldr r9, =0x03 bl lcdSendCommandHalf bl lcdDelay2500us bl lcdSendCommandHalf bl lcdDelay250us bl lcdSendCommandHalf bl lcdDelay250us ldr r9, =0x02 bl lcdSendCommandHalf bl lcdDelay250us ldr r9, =0x28 bl lcdSendCommand ldr r9, =0x08 bl lcdSendCommand ldr r9, =0x01 bl lcdSendCommand bl lcdDelay2500us ldr r9, =0x06 bl lcdSendCommand ldr r9, =0x0C bl lcdSendCommand ldmfd SP!, {r0,r5-r7,r9,r10,PC} EXPORT lcdFirstInit ; вывод строчки на экран, первый байт - адрес ОЗУ LCD, признак конца строки - 0 ; IN ; r0 - адрес строчки lcdPrintString stmfd SP!, {r0,r5-r7,r9,r10,LR} ldr r5, =LCD_RS_LINE ldr r6, =LCD_E_LINE ldr r7, =PIO_BASE ; команда установки адреса ldrb r9, [r0], #1 orr r9, r9, #0x80 bl lcdSendCommand ; теперь выводим символы lcdPrintString_loop ldrb r9, [r0], #1 tst r9, r9 beq lcdPrintString_exit bl lcdSendData b lcdPrintString_loop lcdPrintString_exit ldmfd SP!, {r0,r5-r7,r9,r10,PC} EXPORT lcdPrintString ; установка курсора ; IN ; в r0 - новый адрес курсора lcdSetCursor stmfd SP!, {r0,r5-r7,r9,r10,LR} ldr r5, =LCD_RS_LINE ldr r6, =LCD_E_LINE ldr r7, =PIO_BASE mov r9, r0 orr r9, r9, #0x80 bl lcdSendCommand ldmfd SP!, {r0,r5-r7,r9,r10,PC} EXPORT lcdSetCursor ; вывод строчки на экран, признак конца строки - 0 ; IN ; r0 - адрес строчки lcdPrint stmfd SP!, {r0,r5-r7,r9,r10,LR} ldr r5, =LCD_RS_LINE ldr r6, =LCD_E_LINE ldr r7, =PIO_BASE ; выводим символы lcdPrint_loop ldrb r9, [r0], #1 tst r9, r9 beq lcdPrint_exit bl lcdSendData b lcdPrint_loop lcdPrint_exit ldmfd SP!, {r0,r5-r7,r9,r10,PC} EXPORT lcdPrint END Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 1 февраля, 2011 Опубликовано 1 февраля, 2011 · Жалоба да я знаю, вы меня не задели )) И в мыслях такого не было, боже упаси. Но все же можно было бы причесать перед выкладыванием на всеобщее обозрение - от одних функций задержек (трех аж типов) в глазах рябит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 2 февраля, 2011 Опубликовано 2 февраля, 2011 (изменено) · Жалоба Бросается в глаза, что в оригинальном проекте ничего в OWER не пишется, для "ногодрыгательства" продолжают читаиться и писаться биты ODSR, которые read-only. Приаттачен работающий кусок для 4-х битного режима. На полный проект (лежащий в сети в открытом виде) ссылочку приведу, если надо. Изменено 2 февраля, 2011 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DmitryM 0 2 февраля, 2011 Опубликовано 2 февраля, 2011 · Жалоба Бросается в глаза, что в оригинальном проекте ничего в OWER не пишется, для "ногодрыгательства" продолжают читаиться и писаться биты ODSR, которые read-only. Приаттачен работающий кусок для 4-х битного режима. На полный проект (лежащий в сети в открытом виде) ссылочку приведу, если надо. В ODSR можно писать при соответствующих настройках PIO. Таким образом достигается одновременность выставления, например, шины адреса или данных. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 2 февраля, 2011 Опубликовано 2 февраля, 2011 · Жалоба В ODSR можно писать при соответствующих настройках PIO. Таким образом достигается одновременность выставления, например, шины адреса или данных. Знаю и использую. У автора в приведённом им фрагменте кода настроек не видно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться