Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт окт 31, 2014 17:04:04

yur4ik писал(а):Так вот с ее помощью задаю число, а потом пишу его в переменную key (unsigned int) . Переменная полностью совпадает с тем что ввел с клавы. Далее это число нужно умножить на регистр IRC1 и разделить на 100, по началу казалось фигней, но когда IRC1 умножаю на любое число походу происходит переполнение и в результате вижу совсем другой конечный результат. Переменная в которую пишу (f) имеет уже тип unsigned long int, но это так и не помогло :(
вот так вот делаю: f=(unsigned int)(ICR1*key/100);
Компилятор ругается мол переполнение: overflow is possible in 16 bit multiplication, casting to 'long' may be required
В чем я прокололся?
вы, как и многие до вас, не учитываете правило неявного преобразования типов операндов в выражениях. а правило таково:
1. при вычислении выражения с двумя операндами значения обоих операндов приводятся к наибольшему (по размеру) типу этих операндов.
2. если оба операнда имеют тип char - оба преобразуются к int.
3. результат вычисления выражения имеет тот же тип, что и операнды.
4. после того, как выражение вычислено к результату применяется правило приведения типа так же, как было сказано. если больше вычислений в операторе нет - тип результата приводится к типу переменной, принимающей значение.

итак, разберем ваш пример.
переменная а имеет тип long (знак пока роли не играет). поэтому то, что результату выражения (ICR1 * key / 100) вы принудительно назначаете тип int - ничего не меняет, после того, как вы измените тип на int он будет снова ПРИНУДИТЕЛЬНО изменен на тип, соответствующей f, т.е. long. ваше действие БЕССМЫСЛЕННО.
теперь смотрим на выражение. оно вычисляется слева направо, т.е. сначала вычисляется ICR1 * key. key у вас char, поэтому без всяких рассуждений превращается в int. ICR1, как я понимаю, уже имеет тип int. результат выражения тоже будет int!!! но при умножении int * int результат может быть long - вот ваша проблема! и компилятор об этом вас честно предупреждает - скажите ему спасибо.
что же надо сделать, чтобы исправить ситуацию? надо заставить компилятор считать, что в умножении участвует хотя бы один операнд long - никак иначе! то есть вам надо не тип результата менять, а тип операнда!
то есть решением будет f= (long)ICR1 * key / 100; для страховки я бы еще и к константе 100 приписал суффикс L, чтобы она тоже считалась не int-ом, а long-ом. итак, окончательное решение: f= (long)ICR1 * key / 100L;

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт окт 31, 2014 20:15:49

:o во я бестолковый... Огромное спасибо за столь подробное объяснение :beer: все теперь работает четко :)

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт окт 31, 2014 20:55:21

ARV писал(а):итак, окончательное решение: f= (long)ICR1 * key / 100L;
Помоему, если одно из значений long, то остальные автоматом подтягиваются под long... так что после 100 - L можно и не писать...

Я как то тоже долго разбирался с этими нюансами :)...
viewtopic.php?p=2124491#p2124491
viewtopic.php?p=2124706#p2124706

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 01, 2014 10:50:34

обьясните почему

Код:
for(i=0;i<9;++i)
{}


for(i=0;i<9;i++)
{}


программа выполняется и в первом и во втором случае все равно 9 раз? в протеусе

ведь читаем из лебедева:

i=0 и i<9 выполняем цикл;
дальше- i++ = 0
смотрим на i<9 выполням дальше

i=0,0,1,2,3,4,5,6,7,8 -10 раз


----------

i=0 и i<9 выполняем цикл;
дальше ++i = 1

смотрим 1<9 выполняем

i=0,1,2,3,4,5,6,7,8 - уже 9 раз


----------

почему в протеусе все не так- это глюк или я чего то не пойму?

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 01, 2014 14:01:42

Потому что результат команды инкремента никуда не записывается, а сама она в обоих вариантах всего лишь увеличивает аргумент на 1.
Код:
int i=5;
int x,y;
x=i++;
y=++i;
//i=7; x=5; y=7;

А цикл for разворачивается во что-то вроде
Код:
for(i=0;i<9;i++){/*code*/}

Код:
i=0;
label_cycle:
     if(i<9)goto label_ start; else goto label_end;
label_start:
     /*code*/
     i++;
     goto lebel_cycle;
label_end:

Таким образом, будет выполнено 9 итераций со значениями i=0,1,2,3,4,5,6,7,8.
(извиняюсь за использование goto, это было только для наглядности)

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 01, 2014 18:05:29

COKPOWEHEU писал(а):Потому что результат команды инкремента никуда не записывается, а сама она в обоих вариантах всего лишь увеличивает аргумент на 1.


спс ,подскажите почему PORTD.1=1 за весь цикл,это ведь побитовое или ,а получается 1 за весь цикл что за бред?,или это ошибка в протеусе?

Код:
#include <mega8.h>
#include <delay.h>
unsigned char data,i;
char array[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};


void main(void)

{
PORTD=0x00;
DDRD=0x07;
 while(1)
 { 
 data=0;
for(i=0;i<9;i++)

{
PORTD.1=array[data++]|0x00;
PORTD.0=1;
PORTD.0=0;
}
 PORTD.2=1;
PORTD.2=0;
delay_ms(1000);
         
 
}

 
}

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт дек 12, 2014 00:20:41

не могу сообразить, как реализовать задержку на АВР в несколько часов?

допустим при включении контроллера светик горит 3 минуты, выключается и не горит 3 часа, и так по кругу.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт дек 12, 2014 07:15:40

Код:
unsigned int i;

void main() {
PORTA=0;
DDRA=0xFF;
 while(1)
 {
   PORTA=0xFF; //зажигаем светик
   for(i=0;i<3*60;i++)//ждём 3 минуты
   {
     Delay_ms(1000); //задержка в секунду
   }
   PORTA=0; //гасим светик
   for(i=0;i<3*60*60;i++)//ждём 3 часа
   {                   //3*60*60= 10800 укладываемся в int
     Delay_ms(1000);
   }
   // и всё с начала
 }
}
Последний раз редактировалось alex_ Пт дек 12, 2014 08:26:44, всего редактировалось 1 раз.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт дек 12, 2014 07:33:13

sirha писал(а):спс ,подскажите почему PORTD.1=1 за весь цикл,это ведь побитовое или ,а получается 1 за весь цикл что за бред?,или это ошибка в протеусе?

А ничего что, PORTD.1 тип переменной bit, а array это char, кстати что хотел в итоге то получить?

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт дек 12, 2014 13:22:07



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

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт дек 12, 2014 13:52:17

Как вариант прерывание, или в цикле устанавливаешь опрос кнопки, если кнопка была нажата то выполняем какое либо действие или выход из цикла.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб дек 13, 2014 00:13:51

Почему ругается на первую строку? Просит скобку (
const uint8_t str_setup[7][4]=
{
{0x78, 0xD0, 0x3F, 0x71},
{0x78, 0xD0, 0x3F, 0x54},
{0xF3, 0x00, 0x3F, 0x54},
{0xF3, 0x3F, 0x71, 0x71},
{0x37,0x0,0x7F, 0xF3 },
{0x5C,0x0,0x7F, 0xF3 },
{0x73,0x0,0x7F, 0xF3 }
},
str_setup_1digit[]={0x06, 0x5B, 0xF3, 0xF3, 0x37, 0x5C, 0x73};

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб дек 13, 2014 08:34:52

Может строку со столбцом попутал? Или может вообще стереть значения из квадратных скобок?

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс дек 14, 2014 21:31:46

лови друх :tea:
http://www.c-cpp.ru/books/inicializaciya-massiva

лень писать, поэтому только так

Re: Нескольно простых вопросов о программировании AVR на Си.

Вт дек 16, 2014 07:25:48

Скорее всего, забыли что-то подключить, где определяется это :
uint8_t
Попробуйте заменить на unsigned char

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн мар 02, 2015 18:58:12

Уважаемые КОТЫ!! А как опросить весь порт сразу? Я думал так:
i=PORTD;
и решил вывести данные сразу же на другой порт :
PORTB=i;
не получилось. подскажите что не так!!!
CVAVR

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср мар 04, 2015 12:05:45

Подскажите пожалуйста, есть такая операция сброса бита, её часто встречаю, например

LED_PORT = LED_PORT & ~(1<<LED2);

Понятно что она делает, а вот такая операция

LED_PORT = LED_PORT & (0<<LED2);

разве не делает тоже самое? И логичнее выглядит

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср мар 04, 2015 12:14:51

а что по твоему делает матильда ~ ?

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср мар 04, 2015 12:20:35

Инвертирует результат в скобках

Re: Нескольно простых вопросов о программировании AVR на Си.

Ср мар 04, 2015 12:24:36

тоесть инвертирует установленный вами бит порта
а что происходит с остальными битами порта ?
Ответить