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

Что неправильно в коде ?

Чт мар 24, 2022 13:16:00

Здравствуйте Уважаемые форумчане. Я начинающий сражение с программированием в AVR Studio. Так что начинаю с азов, и сразу же наткрулся на подводный камень.
Написал вот такую короткую программку на высвечивании «1», «2», или «3» при нажатии на кнопки «1», «2», или «3»подключенные к ногам В0, В1, В2 порта «В». Вот текст:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>


segchar (unsigned char seg) //Объявление функции "segchar" c переменной seg
{
if (PINB=0b11111110) // Проверка условия содержимого порта "В"
{
seg = 1; // Если порт "В"=11111110 то переменная seg=1
}
if (PINB=0b11111101) // Проверка условия содержимого порта "В"
{
seg = 2; // Если порт "В"=11111101 то переменная seg=2
}
if (PINB=0b11111011) // Проверка условия содержимого порта "В"
{
seg = 3; // Если порт "В"=11111011 то переменная seg=3 }
}
//----------
int main(void) // Главный цикл
{
DDRD = 0xFF; // Установка порта на выход
DDRB = 0x00; // Установка порта на вход
PORTD = 0b00000000; // Установка содержимого порта "D" в "00000000"
PORTB = 0b00000000; // Установка содержимого порта "B" в "00000000"
seg = 0; // Присвоение переменной "seg" значения "0"
while(1) // Начало беконечного цикла
{
if seg=1; // Проверка условия если seg=1
{
PORTD = 0b11111001; // порт "D" в "11111001", "1" 7-сегментн.
}
if seg=2; // Проверка условия если seg=2
{
PORTD = 0b10100100; // порт "D" в "10100100" "2" 7-сегментн.
}
if seg=3; // Проверка условия если seg =3
{
PORTD = 10110000; // порт "D" в "10110000" "3" 7-сегментн.
}
segchar(seg); // Переход на функцию "segchar"
_delay_ms(500); // Задержка пол секунды
}
}
При попытке скомпилировать, процесс идет с ошибками, компиляция не удается и выводятся вот твкие сообщения:

Warning 1 #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed" c:\program files\atmel\avr studio 5.0\avr toolchain\bin\../lib/gcc/avr/4.5.1/../../../../avr/include/util/delay.h 94 3 test09
Warning 2 return type defaults to 'int' ......\test09.c 9 1 test09
Warning 3 suggest parentheses around assignment used as truth value ......\test09.c 11 3 test09
Warning 4 suggest parentheses around assignment used as truth value ....\test09.c 15 3 test09
Warning 5 suggest parentheses around assignment used as truth value .....\test09.c 19 3 test09
Error 6 'seg' undeclared (first use in this function) .....\test09.c 33 2 test09
Error 7 each undeclared identifier is reported only once for each function it appears in ...\test09.c 33 2 test09
Error 8 expected '(' before 'seg' .......\test09.c 36 6 test09
Error 9 expected '(' before 'seg' ........\test09.c 40 6 test09
Error 10 expected '(' before 'seg' ........\test09.c 44 6 test09
Warning 11 large integer implicitly truncated to unsigned type .......\test09.c 46 3 test09
Warning 12 control reaches end of non-void function ......\test09\test09.c 23 1 test09

Прошу не пинать больно ногами, я только учусь.
Хотел поправить - не получается, плоха читаемость текста программы, почему-то удаляются все множественные пробелы.

Re: Что неправильно в коде ?

Чт мар 24, 2022 13:51:39

ну, как минимум, проверка условия это "==", а не "="

Re: Что неправильно в коде ?

Чт мар 24, 2022 13:58:01

а ещё неверный алгоритм. немного изменить проверку в главном цикле, и все проверки segchar превратятся в
seg = PINB & 0b00000011;
а значит, её вообще можно выкинуть как функцию, а написать это сразу в главном цикле.
Код:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

//----------
int main(void) // Главный цикл
{
   DDRD = 0xFF; // Установка порта на выход
   DDRB = 0x00; // Установка порта на вход
   PORTD = 0b00000000; // Установка содержимого порта "D" в "00000000"
   PORTB = 0b00000000; // Установка содержимого порта "B" в "00000000"
   while(1) // Начало беконечного цикла
   {
      switch (PINB)
      {
         case 0b11111110:
            PORTD = 0b11111001;
            break;
         case 0b11111101:
            PORTD = 0b10100100;
            break;
         case 0b11111011:
            PORTD = 0b10110000;
            break;
         //default:
            //PORTD = 0b00000000;
      }
      _delay_ms(500); // Задержка пол секунды
   }
}
Последний раз редактировалось Martian Чт мар 24, 2022 15:18:52, всего редактировалось 3 раз(а).

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:02:06

рекомендую почитать учебник Прокопенко В.С. Программирование микроконтроллеров ATMEL на языке С

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:11:45

О, подсветка работает! Ура! Спасибо, nds :)

Добавлено after 4 minutes 35 seconds:
Хотел поправить - не получается, плоха читаемость текста программы, почему-то удаляются все множественные пробелы.
оформляйте в тег code

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:15:27

Martian, seg = PINB & 0b00000011; не прокатит у ТС 3 кнопки, первая на пинб.0, вторая на пинб.1, третья не их сумма, а пинб.2
поэтому простое присвоение не катит

Добавлено after 3 minutes 22 seconds:
И зачем сначала переменную проверять, а затем заполнять?
контроллеру, конечно, без разницы (и то если переменная не локально объявлена),
а читать неудобно и можно ошибок наделать.

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:36:05

Ivanoff-iv, ну, я просто взял это:
if (PINB=0b11111110)
if (PINB=0b11111101)
if (PINB=0b11111011)
и увидел, что вполне однозначно идентифицируется по двум последним битам. только 1 и 2 меняются местами. Верно ли вообще состояние порта - то мне неведомо.

Добавлено after 2 minutes 55 seconds:
И зачем сначала переменную проверять, а затем заполнять?
Вроде, тут не нарушений. Изначально она инициализируется, и, алгоритм может предполагать при включении обработку условия именно со значением при инициализации :dont_know:

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:44:27

я бы упрощал как-раз вывод:
объявил бы массив с описанием цифр:
Код:
uint8_t TSIFRI[]={0,0b10100100,0b11111001,0b10110000};
и его элемент с номером нажатой кнопки отправлял бы в порт, к которому подключен индикатор:
Код:
PORTD = TSIFRI[seg];

_____
если смотреть только 2 младших бита, то состояние "нажата 3я кнопка" и "все кнопки отпущены" совпадут...

_____
Да, нарушений нет, но такой код немного труднее понимать и могут внезапно вылезти подводные грабли:
например, если переменную объявить локально, может выйти так, что она не будет сохранена для следующей итерации цикла... (это ведь новичок пишет, он тут может и не заметить)

ПС: кстати я не вижу, где объявляются переменные? сам я в кодевижене работаю, но, думаю, что и студия так, как написано не примет.
Последний раз редактировалось Ivanoff-iv Чт мар 24, 2022 14:47:21, всего редактировалось 1 раз.

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:48:24

Согласен.
Вариантов решения много, но правильный, это, конечно, ссылка на книжку, а также реализация их всех, в том числе вариант самого автора (написать правильно условия, не забыв скобки)

Добавлено after 1 minute 6 seconds:
ПС: кстати я не вижу, где объявляются переменные
прям перед while()

Re: Что неправильно в коде ?

Чт мар 24, 2022 14:52:40

но правильный, это, конечно, ссылка на книжку
это сарказм? я сам по этой книжке учился, там буквально с 20 по 30ю страницы подробно расписано именно то, что ТС нужно.

Про объявление: так, первое упоминание переменной вижу, но где её тип указан? или в студии как в PHP тип меняется в зависимости от внесённого в переменную значения? :shock:

Re: Что неправильно в коде ?

Чт мар 24, 2022 15:20:41

Ivanoff-iv, нет, никакого сарказма. Я довольно-таки фанатично придерживаюсь правила, что чтение книг есть обязательное условие нахождения ответов и решений.
Да, про тип как-то не увидел, каюсь.

Итого, 3 ошибки:
неверное объявление переменной (отсутствует тип);
неверное условие сравнения (= вместо ==);
неверный синтаксис условия (отсутствуют скобки).

Ну и не очень оптимально, чем, наверное, на данном этапе можно пренебречь.

Добавлено after 12 minutes 32 seconds:
если смотреть только 2 младших бита, то
О, блин! Н-да, что-то туплю :oops:
исправил )

Re: Что неправильно в коде ?

Чт мар 24, 2022 15:37:47

[uquote="Martian",url="/forum/viewtopic.php?p=4203109#p4203109"]а ещё неверный алгоритм. немного изменить проверку в главном цикле, и все проверки segchar превратятся в , .....
Огромное спасибо, буду разбираться как это работает.
Вначале была снова ошибка, но ввел объявление переменной "seg" и сборка и компиляция прошли успешно.
Но когда попытался эмулмровать в Протеусе, ничего не вышло, что-то быстро промелькнуло и загорелась "8", т.е. все сегменты индикатора зажглись, на нажатие кнопок нет реакции.

Re: Что неправильно в коде ?

Чт мар 24, 2022 15:58:11

Martian, а разве подтяжку к плюсу включать не надо? Скачал книгу,изучаю

Re: Что неправильно в коде ?

Чт мар 24, 2022 16:04:04

подтяжки - это может и внешне решено быть, или даже только внешне (я не помню архитектуру портов у AVR)

Re: Что неправильно в коде ?

Чт мар 24, 2022 16:05:23

[uquote="Martian",
Итого, 3 ошибки:
неверное объявление переменной (отсутствует тип);
неверное условие сравнения (= вместо ==);
неверный синтаксис условия (отсутствуют скобки).

Ну наконец какие-то подвижки. Постарался в ствоем тексте ввести вышеуказанные поправки,
объявил переменную с типом,
Поправил условия сравнения на ==
и в условиях ввел скобки.
Теперь текст скомпилировался без ошибок. Но при эмуляции все время горит "3"
Я так понял, что идет перебор по порядку от 1 до 3, но задержка после "3" и поэтому все время видна "3", хотя цикл выполняется.
Специально для проверки ввел задержку после "1" и "2". И теперь в Протеусе в цикле загораются "1", "2" и "3". А на кнопки никакой реакции.
Идея программы была такая, чтобы при запуске 7-сегментный индикатор был пустой, т.е. порт "D" со всеми нулями. А при нажатии кнопок подключенных к "В0", "В1" или "В2" загорались соответственно цифры "1", "2" или "3".

Re: Что неправильно в коде ?

Чт мар 24, 2022 16:11:28

значит, пришло время изучать, что такое отладка. То есть, необходимо поставить в коде breakpoint в том месте, где идёт опрос состояние кнопок, и после остановки посмотреть, чему равно значение переменной.
Но я совершенно не знаю, как это всё делается в Proteus - никогда им не пользовался в таком режиме.

Re: Что неправильно в коде ?

Чт мар 24, 2022 16:56:20

У меня вот так заработал после танцев с бубном (поставил оптимизацию Os)
Код:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

//----------
int main(void) // Главный цикл
{
   char seg;
   DDRD = 0xFF; // Установка порта на выход
   DDRB = 0x00; // Установка порта на вход
   PORTD = 0b11111111; // Установка содержимого порта "D" в "00000000"
   PORTB = 0b11111111; // Установка содержимого порта "B" в "00000000"
   
   while(1) // Начало беконечного цикла
   {
   if (PINB==0b11111110)  { PORTD = 0b11111001;}
   if (PINB==0b11111101)  { PORTD = 0b10100100;}
   if (PINB==0b11111100)  { PORTD = 0b10110000;}

     _delay_ms(500); // Задержка пол секунды
   }
}

Re: Что неправильно в коде ?

Чт мар 24, 2022 19:49:19

У меня вот так заработал после танцев с бубном (поставил оптимизацию Os)

Да, конечно работает, но не так как было задумано.
А задумка была такая, есть МК, к нему к порту "D" подключен 7-сегментны индикатор. А к порту "В" подключены 3 кнопки, к "В0", к "В1" и к "В2". После запуска программы индикатор ничего не высвечивает, а при нажатии на кнопки высвечивает соответствующие цифры.

И кстати, как включать оптимизацию ???

Re: Что неправильно в коде ?

Чт мар 24, 2022 20:06:44

а зачем там задержка?

Добавлено after 5 minutes 20 seconds:
исправляю недочеты:
Код:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

//----------
int main(void) // Главный цикл
{
   DDRD = 0xFF; // Установка порта на выход
   DDRB = 0x00; // Установка порта на вход
   PORTD = 0x00; // Установка содержимого порта "D" в "00000000"
   PORTB = 0xFF; // включение подтяжек
   
   while(1) // Начало беконечного цикла
   {
   if (PINB==0b11111110)  PORTD = 0b11111001;
   if (PINB==0b11111101)  PORTD = 0b10100100;
   if (PINB==0b11111011)  PORTD = 0b10110000;
   }
}

Re: Что неправильно в коде ?

Чт мар 24, 2022 21:03:33

Я уже и забыл где включается оптимизация,сам только сегодня авр студию скачал...
У меня и так индикатор не светится после включения-
DDRD = 0xFF; // Установка порта на выход
DDRB = 0x00; // Установка порта на вход
PORTD = 0b11111111; // Установка содержимого порта "D" в "00000000"
PORTB = 0b11111111; // Установка содержимого порта "B" в "00000000"

Добавлено after 5 minutes 59 seconds:
Project->Configuration Options->Optimization->Os
Ответить