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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
yur4ik
Вымогатель припоя
Сообщения: 613
Зарегистрирован: Сб окт 17, 2009 18:56:05
Откуда: РФ, Башкортостан г.Сибай
Контактная информация:

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

Сообщение yur4ik »

:o во я бестолковый... Огромное спасибо за столь подробное объяснение :beer: все теперь работает четко :)
Нельзя всё знать, достаточно понимать.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

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

Я как то тоже долго разбирался с этими нюансами :)...
viewtopic.php?p=2124491#p2124491
viewtopic.php?p=2124706#p2124706
Аватара пользователя
sirha
Вымогатель припоя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

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

Сообщение sirha »

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

Код: Выделить всё

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 раз


----------

почему в протеусе все не так- это глюк или я чего то не пойму?
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение COKPOWEHEU »

Потому что результат команды инкремента никуда не записывается, а сама она в обоих вариантах всего лишь увеличивает аргумент на 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, это было только для наглядности)
Аватара пользователя
sirha
Вымогатель припоя
Сообщения: 550
Зарегистрирован: Ср авг 17, 2011 23:12:30

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

Сообщение sirha »

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);
         
 
}

 
}
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

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

Сообщение mastech »

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

допустим при включении контроллера светик горит 3 минуты, выключается и не горит 3 часа, и так по кругу.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

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

Сообщение alex_ »

Код: Выделить всё

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 раз.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

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

Сообщение alex_ »

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

А ничего что, PORTD.1 тип переменной bit, а array это char, кстати что хотел в итоге то получить?
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

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

Сообщение mastech »

Спойлер
alex_ писал(а):

Код: Выделить всё

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_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

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

Сообщение alex_ »

Как вариант прерывание, или в цикле устанавливаешь опрос кнопки, если кнопка была нажата то выполняем какое либо действие или выход из цикла.
Mikhail
Родился
Сообщения: 9
Зарегистрирован: Пт май 04, 2007 22:32:16
Откуда: Великий Новгород
Контактная информация:

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

Сообщение Mikhail »

Почему ругается на первую строку? Просит скобку (
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};
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

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

Сообщение alex_ »

Может строку со столбцом попутал? Или может вообще стереть значения из квадратных скобок?
pcb
Опытный кот
Сообщения: 833
Зарегистрирован: Пт авг 12, 2011 09:14:27
Откуда: Млечный путь/Земля/РФ/Екатеринбург

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

Сообщение pcb »

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

лень писать, поэтому только так
Разработал:
-BLDC
-ФУОЗ/МПСЗ
-SMART BMS
-ECU/EDC на STM32F4(43%)+CPLD(57%)
-Моноинжектор на ATSAMD20G16
-контроллер эффектов для RGB LED ленты
-умные часы/обратный счет/секундомер
-устройство измерения емкости АКБ
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

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

Сообщение Pink-Pank »

Скорее всего, забыли что-то подключить, где определяется это :
uint8_t
Попробуйте заменить на unsigned char
Fucking static initialization order fiasco
Кот Володька
Родился
Сообщения: 1
Зарегистрирован: Пн мар 02, 2015 18:49:18

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

Сообщение Кот Володька »

Уважаемые КОТЫ!! А как опросить весь порт сразу? Я думал так:
i=PORTD;
и решил вывести данные сразу же на другой порт :
PORTB=i;
не получилось. подскажите что не так!!!
CVAVR
Compressor
Открыл глаза
Сообщения: 41
Зарегистрирован: Пт май 29, 2009 09:38:45

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

Сообщение Compressor »

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

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

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

LED_PORT = LED_PORT & (0<<LED2);

разве не делает тоже самое? И логичнее выглядит
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

а что по твоему делает матильда ~ ?
Tell Me The Truth
Compressor
Открыл глаза
Сообщения: 41
Зарегистрирован: Пт май 29, 2009 09:38:45

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

Сообщение Compressor »

Инвертирует результат в скобках
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

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

Сообщение FreshMan »

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

Вернуться в «AVR»