Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
02.01.2009, 02:28
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Хоть что-то похожее на исходник.
А теперь о основных причинах неработоспособности.
Самая главная причина в попытке работать с портом ввода-вывода через приведение указателя на него к указателю на структуру. Порт это не просто адрес в памяти. Но даже если представить его таковым, то он по свойствам напоминает volatile переменную. Указатель же на порт таким свойством уже не обладает. Соответственно если Вы будете устанавливать, к примеру, последовательно два бита через такое приведение типа, то компилятор заоптимизирует это в ОДИН вывод в порт. Для внешних устройств такая логика несколько неожиданна. Для сборки того, что Вы выложили до этого я добавил
Код:
|
typedef volatile struct
{
unsigned char b0 :1;
unsigned char b1 :1;
unsigned char b2 :1;
unsigned char b3 :1;
unsigned char b4 :1;
unsigned char b5 :1;
unsigned char b6 :1;
unsigned char b7 :1;
} bits; |
Так конечно лучше, но тоже не в любом случае избавит от проблем. Пользуйтесь макросом GCC _BV или стандартными сишными конструкциями:
Код:
|
#define LCD_E 2
#define LCD_E_ON() PORTC |= (1‹‹LCD_E)
// далее в тексте
LCD_E_ON(); |
Еще одно уточнение - файлы исходного текста, с расширением c, не подключаются через инклюд! Это противоречит одному из основных принципов языка - раздельной компиляции. Подсоединяйте такой файл в проект средствами используемой IDE, либо через Makefile, если работаете из командной строки. Иначе в будущем будут вылезать неприятные проблемы. И уж тем более не включайте #include "xxx.c" в H файл.
Попробую собрать, о результатах отпишусь. Но Вы так и не сказали - в чем проблема? Без оптимизации работает в железе? Там задержки конечно раз в 100 подрастут, но индикатор вещь терпеливая, подождет
|
|
|
|
02.01.2009, 03:59
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 583
Сказал спасибо: 76
Сказали Спасибо 90 раз(а) в 66 сообщении(ях)
|
Спасибо за содержательный ответ, но боюсь, я не до конца его понял.
На счет инклудов *.с согласен на 100%
На счет порт - это не просто адрес памяти... какая еще особенность тут добавляется по сравнению с "обычным" регистром из области памяти общего назначения?В этом же месте я не понял про то, в чем проблема Обьясните, пожалуйста ...
P.S. До железа еще далеко... (но оно обязательно будет!!!)
__________________
Sex, Druggs, Rock&Roll
|
|
|
|
06.01.2009, 03:54
|
|
Частый гость
Регистрация: 10.05.2007
Сообщений: 11
Сказал спасибо: 4
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Я использую VMLAB+GCC и без оптимизации получаю асм страшный и ужастный настолько, что даже симулятор от некоторых его инструкций крутит пальцем у виска Переходя на 2-й уровень код (и асм) съёживается в 2 раза и становиться человеческим НО в отладчике 'пропадают' некоторые строки, что и понятно- оптимизация! ИМХО 'без опт' нужен только для отладки своей логики по шагам.
|
|
|
|
25.03.2009, 19:36
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 583
Сказал спасибо: 76
Сказали Спасибо 90 раз(а) в 66 сообщении(ях)
|
Это ужас.
Написал драйвер к клавиатуре. Алгоритм обычный - сканирование по линиям порта (по очереди) и в соответствии с тем, на каком "выходе" клавиатуры появился сигнал, делаю вывод. Ну ужас не в этом. Драйвер я написал, и без оптимизации все работает отлично. Но как только включаю хотя бы 1 уровень, не все кнопки определяются (точнее - половина).
Поглядел дизассемблер. Оптимизатор почему-то вырезает несколько положений "сканера" - и соответсвенно эти клавиши не работают...
Кто подскажет, почему и что делать - цены тому не будет
__________________
Sex, Druggs, Rock&Roll
|
|
|
|
25.03.2009, 20:13
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Сообщение от alberio
|
Кто подскажет, почему и что делать - цены тому не будет
|
Цены не будет точно - телепаты редко встречаются...
|
|
|
|
25.03.2009, 20:55
|
|
Гражданин KAZUS.RU
Регистрация: 08.07.2006
Сообщений: 583
Сказал спасибо: 76
Сказали Спасибо 90 раз(а) в 66 сообщении(ях)
|
Сори.
Прикрепленный файл: 3013875.rar
__________________
Sex, Druggs, Rock&Roll
|
|
|
|
25.03.2009, 22:55
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Мне честно говоря сегодня лень копать глубоко. Но на первый взгляд ничего вроде не выкинуто. Я просто ret-ы посчитал. Оптимизация Os.
Где криминал?
Код:
|
--- keyboard.c -----------------------------------------------------------------------------------
4: {
+0000004E: EF8F SER R24 Set Register
+0000004F: BB8B OUT 0x1B,R24 Out to I/O location
8: KEYDDR=0;
+00000050: BA1A OUT 0x1A,R1 Out to I/O location
10: SET_OUT(LINE_1);
+00000051: 98D8 CBI 0x1B,0 Clear bit in I/O register
+00000052: 9AD0 SBI 0x1A,0 Set bit in I/O register
11: portval=KEYPIN;
+00000053: B389 IN R24,0x19 In from I/O location
12: if(!(portval&(LINE_2)))
+00000054: FD81 SBRC R24,1 Skip if bit in register cleared
+00000055: C003 RJMP PC+0x0004 Relative jump
+00000056: E383 LDI R24,0x33 Load immediate
+00000057: E090 LDI R25,0x00 Load immediate
+00000058: 9508 RET Subroutine return
14: if(!(portval&(LINE_8)))
+00000059: FD87 SBRC R24,7 Skip if bit in register cleared
+0000005A: C003 RJMP PC+0x0004 Relative jump
+0000005B: E283 LDI R24,0x23 Load immediate
+0000005C: E090 LDI R25,0x00 Load immediate
+0000005D: 9508 RET Subroutine return
16: SET_ALL_IN;
+0000005E: BA1A OUT 0x1A,R1 Out to I/O location
18: SET_OUT(LINE_4);
+0000005F: 98DB CBI 0x1B,3 Clear bit in I/O register
+00000060: 9AD3 SBI 0x1A,3 Set bit in I/O register
20: if(!(portval&(LINE_5)))
+00000061: 99CC SBIC 0x19,4 Skip if bit in I/O register cleared
+00000062: C003 RJMP PC+0x0004 Relative jump
+00000063: E386 LDI R24,0x36 Load immediate
+00000064: E090 LDI R25,0x00 Load immediate
+00000065: 9508 RET Subroutine return
22: SET_ALL_IN;
+00000066: BA1A OUT 0x1A,R1 Out to I/O location
24: SET_OUT(LINE_3);
+00000067: 98DA CBI 0x1B,2 Clear bit in I/O register
+00000068: 9AD2 SBI 0x1A,2 Set bit in I/O register
25: portval=KEYPIN;
+00000069: B389 IN R24,0x19 In from I/O location
26: if(!(portval&(LINE_2)))
+0000006A: FD81 SBRC R24,1 Skip if bit in register cleared
+0000006B: C003 RJMP PC+0x0004 Relative jump
+0000006C: E382 LDI R24,0x32 Load immediate
+0000006D: E090 LDI R25,0x00 Load immediate
+0000006E: 9508 RET Subroutine return
28: if(!(portval&(LINE_5)))
+0000006F: FD84 SBRC R24,4 Skip if bit in register cleared
+00000070: C003 RJMP PC+0x0004 Relative jump
+00000071: E385 LDI R24,0x35 Load immediate
+00000072: E090 LDI R25,0x00 Load immediate
+00000073: 9508 RET Subroutine return
30: SET_ALL_IN;
+00000074: BA1A OUT 0x1A,R1 Out to I/O location
32: SET_OUT(LINE_6);
+00000075: 98DD CBI 0x1B,5 Clear bit in I/O register
+00000076: 9AD5 SBI 0x1A,5 Set bit in I/O register
33: portval=KEYPIN;
+00000077: B329 IN R18,0x19 In from I/O location
34: if(!(portval&(LINE_2)))
+00000078: FD21 SBRC R18,1 Skip if bit in register cleared
+00000079: C003 RJMP PC+0x0004 Relative jump
+0000007A: E384 LDI R24,0x34 Load immediate
+0000007B: E090 LDI R25,0x00 Load immediate
+0000007C: 9508 RET Subroutine return
36: if(!(portval&(LINE_8)))
+0000007D: FD27 SBRC R18,7 Skip if bit in register cleared
+0000007E: C003 RJMP PC+0x0004 Relative jump
+0000007F: E387 LDI R24,0x37 Load immediate
+00000080: E090 LDI R25,0x00 Load immediate
+00000081: 9508 RET Subroutine return
38: if(!(portval&(LINE_5)))
+00000082: FD24 SBRC R18,4 Skip if bit in register cleared
+00000083: C003 RJMP PC+0x0004 Relative jump
+00000084: E388 LDI R24,0x38 Load immediate
+00000085: E090 LDI R25,0x00 Load immediate
+00000086: 9508 RET Subroutine return
40: if(!(portval&(LINE_7)))
+00000087: FD26 SBRC R18,6 Skip if bit in register cleared
+00000088: C003 RJMP PC+0x0004 Relative jump
+00000089: E389 LDI R24,0x39 Load immediate
+0000008A: E090 LDI R25,0x00 Load immediate
+0000008B: 9508 RET Subroutine return
42: SET_ALL_IN;
+0000008C: BA1A OUT 0x1A,R1 Out to I/O location
44: SET_OUT(LINE_2);
+0000008D: 98D9 CBI 0x1B,1 Clear bit in I/O register
+0000008E: 9AD1 SBI 0x1A,1 Set bit in I/O register
45: portval=KEYPIN;
+0000008F: B389 IN R24,0x19 In from I/O location
46: if(!(portval&(LINE_5)))
+00000090: FD84 SBRC R24,4 Skip if bit in register cleared
+00000091: C003 RJMP PC+0x0004 Relative jump
+00000092: E381 LDI R24,0x31 Load immediate
+00000093: E090 LDI R25,0x00 Load immediate
+00000094: 9508 RET Subroutine return
48: if(!(portval&(LINE_8)))
+00000095: FD87 SBRC R24,7 Skip if bit in register cleared
+00000096: C003 RJMP PC+0x0004 Relative jump
+00000097: E380 LDI R24,0x30 Load immediate
+00000098: E090 LDI R25,0x00 Load immediate
+00000099: 9508 RET Subroutine return
50: SET_ALL_IN;
+0000009A: BA1A OUT 0x1A,R1 Out to I/O location
52: SET_OUT(LINE_8);
+0000009B: 98DF CBI 0x1B,7 Clear bit in I/O register
+0000009C: 9AD7 SBI 0x1A,7 Set bit in I/O register
54: if(!(portval&(LINE_7)))
+0000009D: 99CE SBIC 0x19,6 Skip if bit in I/O register cleared
+0000009E: C003 RJMP PC+0x0004 Relative jump
+0000009F: E28A LDI R24,0x2A Load immediate
+000000A0: E090 LDI R25,0x00 Load immediate
+000000A1: 9508 RET Subroutine return
56: SET_ALL_IN;
+000000A2: BA1A OUT 0x1A,R1 Out to I/O location
+000000A3: E080 LDI R24,0x00 Load immediate
+000000A4: E090 LDI R25,0x00 Load immediate
59: } |
|
|
|
|
26.03.2009, 21:55
|
|
Супер-модератор
Регистрация: 12.04.2007
Адрес: Урал
Сообщений: 2,459
Сказал спасибо: 1,463
Сказали Спасибо 6,183 раз(а) в 1,468 сообщении(ях)
|
Цитата:
|
Еще одно уточнение - файлы исходного текста, с расширением c, не подключаются через инклюд! Это противоречит одному из основных принципов языка - раздельной компиляции. Подсоединяйте такой файл в проект средствами используемой IDE, либо через Makefile, если работаете из командной строки. Иначе в будущем будут вылезать неприятные проблемы.
|
Уважаемый Kison! Можно поподробнее объяснить почему не рекомендуете файлы х.с подключать через инклюд? Какие проблемы это может вызвать? И еще, в чем принципиальная разница между х.с и х.h? Нельзя ли х.с (кроме main)сохранить и использовать в дальнейшем с расширением h? И наоборот?
|
|
|
|
27.03.2009, 15:19
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Сообщение от SwanSwan
|
Уважаемый Kison! Можно поподробнее объяснить почему не рекомендуете файлы х.с подключать через инклюд? Какие проблемы это может вызвать? И еще, в чем принципиальная разница между х.с и х.h? Нельзя ли х.с (кроме main)сохранить и использовать в дальнейшем с расширением h? И наоборот?
|
Можно конечно. Разделение на с и h файлы условно. Сделано это не для компилятора, а для удобства программиста. Смысл этого в разбиении программы на функционально законченные модули. Т.е. внутри модуля содержатся данные и методы их обработки, упрощенный аналог класса в С++. Один раз создав/отладив такой автономный модуль, в дальнейшем просто включаем его в другие проекты. Удобно? Несомненно.
Но сам по себе модуль бесполезен. Нам нужно дать доступ к его функциям и данным из других модулей. Вот для этого и придуман h файл - интерфейсный или заголовочный. Если в самом модуле находятся объявления переменных и определения функций, т.е. то, что приводит к реальному выделению памяти, то в интерфейсном находятся только их описания. Так как реального выделения памяти не происходит, то h файлы могут подключаться куда угодно и сколько угодно раз. Они в общем случае нужны для контроля компилятором типов переменных и параметров функций. А вот сам модуль (с файл) должен быть только один.
Основное различие между с и h файлами в том, что первый требует выделения памяти под переменные и функции, а второй нет.
Можно конечно и через include подключить все модули в один с файл. Приведет это к тому, что препроцессор свалит в него весь исходник оптом. И именно его и будет обрабатывать компилятор. При отладке по исходному тексту именно по этому сборному файлу и придется вести отладку. При достаточно большом проекте этот файл может стать в несколько тысяч строк. И еще момент - компилятор будет всегда обрабатывать весь этот файл целиком. Сборка некоторых проектов может занимать 20 минут и более. При раздельной компиляции заново компилируется только то, что изменилось с момента предыдущей. А при написании/отладке этот процесс повторяется многократно. Изменили функцию в одном модуле - перекомпилируется только он. Вместо 20 минут копиляция займет 10 секунд. Для маленьких проектов(AVR) время полной сборки небольшое, но лучше сразу привыкнуть делать правильно. Это если есть цель расти профессионально. Перестроить навыки намного сложней, чем изначально приобрести правильные.
Вторая функция h файла - дать модулю доступ к библиотечным функциям. Библиотеки - такие же модули! Они хранятся обычно в виде откомпилированных заранее объектников. Для сокращения времени сборки.
Вот еще пример показательный. Допустим проект из трех модулей - main.c, a.c, b.c. Функции из модуля а вызывают функции из b и наоборот. При отсутствии заголовочных файлов и подключения модулей в main.c через include встает вопрос, какой из файлов a или b подключать первым. Можно выкрутиться из этого добавив в a.c описание функций из b.c и наоборот. Но представим ситуацию - мы изменили параметр функции в a.c. Нам придется изменить и описание в b.c. На первый взгляд ничего страшного. Но что если модулей больше, например 30. И все они пользуются этой функцией из a.c. Придется 30 раз править описание измененной функции. Если же делать правильно, то достаточно изменить только одно описание - в h файле. В программе часто встречаются перекрестные связи между модулями, использование заголовочных файлов избавляет от рутинной работы - правки кучи модулей при изменении в одном.
Да, оказывается трудно рассказать очевидное
Слишком много букв писать нужно. Вот тут почитайте - http://program.rin.ru/razdel/html/171.html
|
|
|
Эти 4 пользователя(ей) сказали Спасибо kison за это сообщение:
|
|
|
27.03.2009, 16:55
|
|
Супер-модератор
Регистрация: 12.04.2007
Адрес: Урал
Сообщений: 2,459
Сказал спасибо: 1,463
Сказали Спасибо 6,183 раз(а) в 1,468 сообщении(ях)
|
Спасибо за обстоятельный ответ. Но не понял, что изменится при подключении файлов a и b через IDE, а не через инклюд? Разве там не встанет вопрос об очередности подключений? И потом после компиляции отладку в любом случае будем вести по одному сборному файлу.
Ссылка выдает ошибку 404.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Тема |
Автор |
Раздел |
Ответов |
Последнее сообщение |
Оптимизация программы - бортовой компьютер на PIC16F73
|
Hellka |
Микроконтроллеры, АЦП, память и т.д |
6 |
06.09.2010 17:04 |
gcc, iar, code vision AVR ?
|
schotki |
Микроконтроллеры, АЦП, память и т.д |
48 |
26.05.2009 20:15 |
AVR+GCC+jacOS
|
DenisLeonidovich |
Микроконтроллеры, АЦП, память и т.д |
3 |
24.07.2007 14:24 |
GCC AVR не работает printf("Hello word")
|
Kabron |
Proteus, KiCAD и другие ECAD |
8 |
03.03.2007 14:33 |
GNU GCC AVR вопрос по переменным..
|
Mozart |
Микроконтроллеры, АЦП, память и т.д |
3 |
09.02.2007 20:00 |
Часовой пояс GMT +4, время: 04:47.
|
|