|
Программирование МК на Си, Вопроосы по коду |
|
|
|
Dec 27 2011, 13:53
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Здравствуйте. Возникло пару вопросов начального уровня по программированию МК на Си. 1) Подскажите как расчитать время задержки, если частота на микроконтроллере 9 МГц. Пример кода ниже. Я считаю так: для первого Delay, каждые 111 нс (9МГц) от числа 82 (загруженного из Delay1) будет отниматься 1, когда дойдет до нуля цикл завершится. Получим задержку 111 нс * 82 = 9.102 мкс. 2) Почему переменная j инициализируется числом 1000. Код void Delay1(unsigned int j) { while(j--) Delay(82); }
void Delay(unsigned int i) { while(i--); } 3) В uVision есть окно прерываний (рисунок). EA - общий запрет/разрешение прерываний. EX0 - разрешение внешнего прерывания INT0. Не до конца понял назначение IT0 и не понял IE0. 4) Поясните код Код void INTRPT0(void) interrupt 0 using 1 , ето что специальная функция на СИ, которая срабатывает когда на ноге INT0 появляется "0". 5) Что возвратит строка Код return !INT0; , если sbit INT0 = 0xB2 и на порту INT0 лог. "0". Будет возвращена "1". 6) #define ADDR 0x02 #define ERROR PBYTE[ADDR] Если я напишу ERROR (0xFF), во внешнюю память запишется данные 0xFF? Просто данные без адреса? Заранее благодарю за ответы.
Эскизы прикрепленных изображений
|
|
|
|
|
Dec 27 2011, 14:45
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Хорошо бы задавая вопрос указывать конкретный тип МК, для которого Вы пишите программу... Я, так понял, что какой-то клон 51 серии...
1. Каждый оператор языка Си вовсе не обязательно выполняется за один такт процессора. Оператор языка Си, обычно (не всегда, конечно), переводится транслятором в несколько команд. Каждая команда в МК51 выполняется за несколько (от 1 до 3) циклов процессора; каждый цикл - несколько (в "классике" - 12) тактов генератора... В общем случае нужно по ассемблерному коду посчитать время выполнения функции Delay от её аргумента - зависимость будет, примерно, такой: Т= X * i + Y в циклах процессора...
PS. Если в настройках проекта правильно указать тип МК и тактовую частоту, то в отладчике можно посмотреть время выполнения участка программы.
2. Не понятно: о чём идёт речь?
3. Это - соответствующие биты регистра TCON
4. В МК есть такое понятие - "прерывание". При определенных условиях происходит прерывание "естественной" последовательности команд, и переход на процедуру обработки прерывания. Стандарт языка Си не предусматривает прерываний. Приведенная Вами конструкция - заголовок процедуры прерывания.
5. В общем случае - возвратит "не ноль".
6. Если Вы запишите ERROR= 0xFF; то во внешнюю память по адресу 2 (поскольку ADDR то же самое, что 0х02 = 2) будет записано FF
|
|
|
|
|
Jan 3 2012, 11:32
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Цитата 2. Не понятно: о чём идёт речь? Изначально переменная j инициализируется нулем, но после первого инкремента while(j--) в ней появляется число 03Е7h = 999b. Почему так ? Цитата 4. В МК есть такое понятие - "прерывание". При определенных условиях происходит прерывание "естественной" последовательности команд, и переход на процедуру обработки прерывания. Стандарт языка Си не предусматривает прерываний. Приведенная Вами конструкция - заголовок процедуры прерывания. То есть процедура будет выполнена когда на INT0 появится "0". Цитата 5. В общем случае - возвратит "не ноль". Можно подробней? Еще вопрос: Есть цепочка вызовов функций на Си, не понятен результат в IS_ER. Код #define IS_ER (!(GetERROR()&0x10))
while(1) { ....................................
if(!IS_ER) return; }
GetERROR(void) { return (ERROR|0x8F); } Понимаю так, когда программа доходит до if(!IS_ER), она проверяет что в переменной IS_ER, там функция GetERROR, смотрит ее, там еще одна функция ERROR(определение функции ERROR в первом посте). С внешней памяти с ячейки под адресом 0x02 считывает данные (8 разрядный код), далее над ними выполнится по битная операция ИЛИ и числом 0x8F. Результат будет так же иметь 8 бит. Далее, результат подставится в место вызова, а это GetERROR(), тут над результатом функции и числом 0х10 выполняется логическое И результат инвертируется и передается в IS_ER. Если так размышлять то в IS_ER попадет 8 битное число, чего быть не может, ведь там IF. Где я ошибаюсь?
Сообщение отредактировал Mackeda - Jan 3 2012, 11:33
|
|
|
|
|
Jan 3 2012, 12:00
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(Mackeda @ Jan 3 2012, 15:32)  но после первого инкремента while(j--) нет, после декрементаЦитата(Mackeda @ Jan 3 2012, 15:32)  Еще вопрос: Есть цепочка вызовов функций на Си, не понятен результат в IS_ER. Код #define IS_ER (!(GetERROR()&0x10)) while(1) { ....................................
if(!IS_ER) return; } Понимаю так, когда программа доходит до if(!IS_ER), она проверяет что в переменной IS_ER это не переменная. Препроцессор сгенерит вот такой код, который скормится компилятору Код #define IS_ER (!(GetERROR()&0x10)) while(1) { ....................................
if(!(!(GetERROR()&0x10))) return; } после выполнения всех битовых операций результат будет подставлен в if в результате получим: GetERROR()&0x10 - выделяем 4-й бит побитовая инверсия результата еще одна инверсия далее if проверяет результат - если он будет НЕ НОЛЬ, то выполнится тело if
|
|
|
|
|
Jan 3 2012, 12:32
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Цитата нет, после декремента Сори за опечатку, да после дикремента, том почему так? Цитата далее if проверяет результат - если он будет НЕ НОЛЬ, то выполнится тело if Если результат постоянно будет "1", программа не выйдет из цикла while(1)?
|
|
|
|
|
Jan 3 2012, 12:44
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(Mackeda @ Jan 3 2012, 16:32)  Сори за опечатку, да после дикремента, том почему так? смотрите допустим, имеем беззнаковую переменную размером 8 бит инициализируем нулем (00000000b) теперь пробуем вычесть из нее 1 получаем 11111111b или 0xFF почему у Вас получается другое значение? возможно, в теле цикла переменная еще как-то модифицируется Цитата(Mackeda @ Jan 3 2012, 16:32)  Если результат постоянно будет "1", программа не выйдет из цикла while(1)? да
|
|
|
|
|
Jan 3 2012, 18:34
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Mackeda @ Jan 3 2012, 15:32)  Изначально переменная j инициализируется нулем, но после первого инкремента while(j--) в ней появляется число 03Е7h = 999b. Почему так ? Что значит "переменная j инициализируется нулем" ? В данном случае: j - параметр функции Delay1; вероятно, в программе есть вызов функции Delay1(1000); при этом переменная j (та самая, которая - параметр функции Delay1, возможно, есть ещё одна переменная j, которая "инициализируется нулём" - это совсем другая переменная) примет значение 1000, а после дикремента - значение 999. Цитата(Mackeda @ Jan 3 2012, 15:32)  То есть процедура будет выполнена когда на INT0 появится "0". Если быть формалистом, то процедура будет выполнена, если установлен флаг IE0 в регистре TCON, при этом установлены EX0 и EA в регистре IE. Для "классики" этого достаточно (в других МК могут быть ещё условия). Неважно - каким образом оказался установленным бит IE0 (выполнилось условие, установленное битом IT0 регистра TCON, или, например, некоторой командой). Цитата(Mackeda @ Jan 3 2012, 15:32)  Можно подробней? Результат логической операции - ноль (ложь), или "не ноль" (любое значение, отличное от нуля).
|
|
|
|
|
Jan 10 2012, 10:04
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Подскажите еще момент. Код while(1) { if(!ERROR1) { ........... return 1; } else if(ERROR1) .............. return 0; Программа выйдет из цикла while когда !ERROR1 будет равен "0", а при "1" зависнет в цикле?
|
|
|
|
|
Jan 10 2012, 10:32
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
А как надо ? какая-то ахинея. Пишите что бы было всегда всем понятно. Код while(1) { if(ERROR1 == 0) { ........... return 1; } else { ........ return 0; } } Только не совсем понят5ен смысл этого кода, который при первой же итерации выйдет.
|
|
|
|
|
Jan 10 2012, 11:18
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Уточняю. Код Выполнение программы:
Шаг 1 ........ Шаг 2 while(Init()==0); // ожидание инициализации (пока не возвратит 0) Шаг 3 ........................
переходит к функции Init
bit Init(void) { while(1) { if(!ERROR1) // проверяет что возвращает функция ERROR1 (она большая поэтому ее не привожу) { ........... return 1; } else if(ERROR2) // проверяет что возвращает функция ERROR2 (тут допустил ошибку в предыдущем коде нужно проверять ERROR2 ) return 0; } } Правильно ли я понял: программа перейдет на Шаг 3, только в случает если ERROR1 = 1, ERROR2 = 1.
|
|
|
|
|
Jan 11 2012, 09:12
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(Mackeda @ Jan 10 2012, 15:18)  Правильно ли я понял: программа перейдет на Шаг 3, только в случает если ERROR1 = 1, ERROR2 = 1. Если учесть, что ваш 'Шаг 2' Цитата Шаг 2 while(Init()==0); // ожидание инициализации (пока не возвратит 0) закончится когда Init() вернет не 0 (в коментарии у вас написанно ровно наоборот), то 'Шаг 3' наступит когда ERROR1 вернет 0
|
|
|
|
|
Jan 13 2012, 08:32
|
Местный
  
Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315

|
Проверять значение вызываемой функции надо так Код if (ERROR!()) { return 1; } иначе проверяется указатель или адрес функции (в примере отсутствуют скобки после имени функции)
--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
|
|
|
|
|
Jan 18 2012, 13:20
|
Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092

|
Цитата Если быть формалистом, то процедура (прерывания) будет выполнена, если установлен флаг IE0 в регистре TCON, при этом установлены EX0 и EA в регистре IE. Для "классики" этого достаточно (в других МК могут быть ещё условия). Неважно - каким образом оказался установленным бит IE0 (выполнилось условие, установленное битом IT0 регистра TCON, или, например, некоторой командой). А можно программно установить на ноге INT 0 уровень логического нуля? Или эта нога только как вход работает.
|
|
|
|
|
Jan 21 2012, 06:02
|
Группа: Новичок
Сообщений: 3
Регистрация: 17-01-12
Пользователь №: 69 612

|
Здравствуйте! Сейчас пишу первый проект на микроСи, до этого работал только на асме для микрочипа. Не могу разобраться что происходит. Подскажите пожалуйста. Код dif_res = (delta_1 - delta_0) * Kd; // delta 0 = 760 // delta 1 = 0 // dif_res становится равным 65384, почему, и откуда берётся это число? // signed int delta_0, delta_1, dif_res; // const float Kd = 0.2;
|
|
|
|
|
Jan 21 2012, 07:18
|
Группа: Новичок
Сообщений: 3
Регистрация: 17-01-12
Пользователь №: 69 612

|
Теперь начинаю понимать..., спасибо большое!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|