реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Программирование МК на Си, Вопроосы по коду
Mackeda
сообщение Dec 27 2011, 13:53
Сообщение #1





Группа: Участник
Сообщений: 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? Просто данные без адреса?

Заранее благодарю за ответы.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 27 2011, 14:45
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Mackeda
сообщение Jan 3 2012, 11:32
Сообщение #3





Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jan 3 2012, 12:00
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
Mackeda
сообщение Jan 3 2012, 12:32
Сообщение #5





Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092



Цитата
нет, после декремента


Сори за опечатку, да после дикремента, том почему так?

Цитата
далее if проверяет результат - если он будет НЕ НОЛЬ, то выполнится тело if


Если результат постоянно будет "1", программа не выйдет из цикла while(1)?
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jan 3 2012, 12:44
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 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)?

да
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 3 2012, 18:34
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 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) *
Можно подробней?
Результат логической операции - ноль (ложь), или "не ноль" (любое значение, отличное от нуля).
Go to the top of the page
 
+Quote Post
Mackeda
сообщение Jan 10 2012, 10:04
Сообщение #8





Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092



Подскажите еще момент.

Код
while(1)
       {
    
        if(!ERROR1)
            {
            ...........                
            return 1;
            }
        else
            if(ERROR1)
            ..............    
                        return 0;


Программа выйдет из цикла while когда !ERROR1 будет равен "0", а при "1" зависнет в цикле?
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Jan 10 2012, 10:32
Сообщение #9


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



А как надо ? какая-то ахинея. Пишите что бы было всегда всем понятно.
Код
while(1)
{
   if(ERROR1 == 0)
   {
      ...........                
      return 1;
   }
   else
   {
     ........
     return 0;
  }
}

Только не совсем понят5ен смысл этого кода, который при первой же итерации выйдет.
Go to the top of the page
 
+Quote Post
Mackeda
сообщение Jan 10 2012, 11:18
Сообщение #10





Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 10 2012, 12:04
Сообщение #11


Гуру
******

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



Цитата(Mackeda @ Jan 10 2012, 15:18) *
Правильно ли я понял: программа перейдет на Шаг 3, только в случает если ERROR1 = 1, ERROR2 = 1.

Точнее будет сказать: если ERROR1 и ERROR2 примут значение, отличное от нуля (единицы тоже подойдут biggrin.gif ).
Go to the top of the page
 
+Quote Post
XVR
сообщение Jan 11 2012, 09:12
Сообщение #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
Go to the top of the page
 
+Quote Post
редактор
сообщение Jan 13 2012, 08:32
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315



Проверять значение вызываемой функции надо так
Код
if (ERROR!())
   { return 1;
     }


иначе проверяется указатель или адрес функции (в примере отсутствуют скобки после имени функции)


--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 13 2012, 11:04
Сообщение #14


Гуру
******

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



Цитата(редактор @ Jan 13 2012, 12:32) *
Проверять значение вызываемой функции надо так
if (ERROR!())

О как у Вас отрицание куда-то "уехало"!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 13 2012, 11:05
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Mackeda @ Jan 10 2012, 15:18) *
Уточняю.

Шаг 1 ........
Шаг 2 while(Init()==0); // ожидание инициализации (пока не возвратит 0)
Шаг 3 ........................


Правильно ли я понял: программа перейдет на Шаг 3, только в случает если ERROR1 = 1, ERROR2 = 1.

Обычно оборачивают так
Код
bit Init(void)  
{
  do{
    if(ERROR1){/*обработка именно ошибочной ситуации*/; break;}
    if(ERROR2){/*обработка ошибочной ситуации 2*/; break;}
    return 1;//успешная инициализация
  }while(0);
  return 0;
}
Go to the top of the page
 
+Quote Post
Mackeda
сообщение Jan 18 2012, 13:20
Сообщение #16





Группа: Участник
Сообщений: 13
Регистрация: 26-12-11
Пользователь №: 69 092



Цитата
Если быть формалистом, то процедура (прерывания) будет выполнена, если установлен флаг IE0 в регистре TCON, при этом установлены EX0 и EA в регистре IE. Для "классики" этого достаточно (в других МК могут быть ещё условия). Неважно - каким образом оказался установленным бит IE0 (выполнилось условие, установленное битом IT0 регистра TCON, или, например, некоторой командой).


А можно программно установить на ноге INT 0 уровень логического нуля? Или эта нога только как вход работает.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 18 2012, 15:33
Сообщение #17


Гуру
******

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



Цитата(Mackeda @ Jan 18 2012, 17:20) *
А можно программно установить на ноге INT 0 уровень логического нуля?

Можно
Go to the top of the page
 
+Quote Post
Vladimir_Sn
сообщение Jan 21 2012, 06:02
Сообщение #18





Группа: Новичок
Сообщений: 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;

Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 21 2012, 06:28
Сообщение #19


Гуру
******

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



Цитата(Vladimir_Sn @ Jan 21 2012, 10:02) *
Не могу разобраться что происходит.

Вспомните (узнайте, если не знали) про дополнительный код. Значение переменной dif_res равно минус 152. Число 65384 имеет такое же представление в памяти, что и минус 152,, но для беззнаковых целых (unsigned int).
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jan 21 2012, 06:39
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



А ещё умножение float на int и присваивание результата в int. Вспомните 1/3 и 1.0/3/0
Но лучше дроби не использовать там где это возможно. Умножение на 0.2 заменяется цельночисленным делением на 5 если точность устраивает. Если нет, то см выше.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Vladimir_Sn
сообщение Jan 21 2012, 07:18
Сообщение #21





Группа: Новичок
Сообщений: 3
Регистрация: 17-01-12
Пользователь №: 69 612



Теперь начинаю понимать..., спасибо большое!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 02:25
Рейтинг@Mail.ru


Страница сгенерированна за 0.01582 секунд с 7
ELECTRONIX ©2004-2016