Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/20: Рейтинг темы: голосов - 20, средняя оценка - 4.75
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
1

Последовательное зажигание светодиодов по кнопке (ATtiny2313, Cи)

18.04.2015, 16:23. Просмотров 3553. Ответов 58
Метки нет (Все метки)

Здравствуйте.Есть такая проблема.Написал код для подпрограммы последовательного зажигания светодиодов.Вот пример:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*****************************************************
Version : Кнопки и светодиоды                                                 
Chip type           : ATmega16
Clock frequency     : 4,000000 MHz
*****************************************************/              
#include <mega16.h>                                      // библиотека ввода\вывода микроконтроллера
#include <delay.h>                                        // библиотека задержки
void i_miganie()
{
                                                                         PORTС.0=1;
                     delay_ms(600);
                                                                     PORTС.1=1;
                                     delay_ms(600);
                                     PORTС.2=1;
                                     delay_ms(600);
                                     PORTС.3=1;
                                     delay_ms(600);
                                     PORTС.4=1;
                                     delay_ms(600);
                                     PORTС.5=1;
                                     delay_ms(600);
                                     PORTС.6=1;
                                     delay_ms(600);
                                     PORTС.7=1;
                                     delay_ms(600);
                                     PORTС.7=0;
                                     delay_ms(600);
                                     PORTС.6=0;
                                     delay_ms(600);
                                     PORTС.5=0;
                                     delay_ms(600);
                                     PORTС.4=0;
                                     delay_ms(600);
                                     PORTС.3=0;
                                     delay_ms(600);
                                     PORTС.2=0;
                                     delay_ms(600);
                                     PORTС.1=0;
                                     delay_ms(600);
                                     PORTС.0=0;
                                     delay_ms(600);                   
}
Получился очень много кода.Как его можно сократить, а то общая программа получается очень большая.Задание такое:Обеспечить при нажатой кнопке SW1 поочередное засвечивание светодиодов LED0… LED7 на 1с в последовательности LED0, LED1,.., LED7, LED0 и т. д. При нажатой кнопке SW4 зажигание светодиодов должно происходить в обратном порядке. Кнопки подключены к порту B, а светодиоды - к порту C.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.04.2015, 16:23
Ответы с готовыми решениями:

Последовательное зажигание светодиодов по кнопке (ATmega8515, ASM)
Добрый день. Требуется помощь для написания программы на ассемблере под AVR...

Последовательное зажигание светодиодов
Собственно задание: при включении МК светодиоды не горят, через 2 с загораются...

Зажигание светодиодов AT90S2313
Доброго времени суток. На AVR только начинающий Вот написал программу для...

Последовательное гашение светодиодов на окружности с интервалом
Помогите пожалуйста! Разработать программу, осуществляющую последовательное...

Последовательное плавное управление яркостью светодиодов
Нужно написать программку на Atmega48 в CodevisionAVR Используя PORTD 0 1 2 С...

58
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
24.04.2015, 01:01  [ТС] 41
Для 30-34 строчки пишет a_prog.c(29): invalid expression
0
Ethereal
5200 / 1943 / 251
Регистрация: 17.02.2013
Сообщений: 2,882
24.04.2015, 01:27 42
Цитата Сообщение от ValeryS Посмотреть сообщение
не думаю что удастся оптимизировать, компиляторы давно уже остаток от деления на степень 2 заменяют на "И"
а деление на сдвиг
Не могут они этого делать.
Вот давай поделим -1 на 2 на Си. Получим частное 0 и остаток -1.
Попробуем получить остаток с помощью И. Получим 1. Значит частное -1.
Попробуем получить частное сдвигом. Получим -1. Значит остаток 1.
И "И" и сдвиг идут лесом.

Вернее не идут, но только для беззнаковых целых. А для знаковых идут.

Добавлено через 8 минут
Так-что %=8 гораздо хуже, чем &=7 . Может такого кода наворотить.
0
ValeryS
Модератор
7446 / 5638 / 716
Регистрация: 14.02.2011
Сообщений: 19,206
Завершенные тесты: 1
24.04.2015, 06:21 43
Цитата Сообщение от Ethereal Посмотреть сообщение
И "И" и сдвиг идут лесом.
а есть такая штука как арифметический и логический сдвиг
Цитата Сообщение от Ethereal Посмотреть сообщение
Получим частное 0 и остаток -1.
остаток от деления отрицательных чисел тайна великая есть
0
Витальич
1274 / 1184 / 174
Регистрация: 02.12.2013
Сообщений: 4,886
24.04.2015, 08:51 44
Цитата Сообщение от gubilon Посмотреть сообщение
if (!PINB.0==0){tmp| = 01;}
if (!PINB.0==0){tmp |= 01;}
Типа палочка должна с ровно без пробела писаться

Добавлено через 4 минуты
Цитата Сообщение от Ethereal Посмотреть сообщение
Это пишется проще
count++;
count &= 7 ;
ИМХО: проще то оно проще, но вопрос задал начинающий и таких изысков еще не знает
0
MS24
11 / 11 / 2
Регистрация: 22.02.2012
Сообщений: 115
Завершенные тесты: 1
24.04.2015, 08:57 45
TC ты об успехах - то пиши, мы за тебя переживаем =)
0
Ethereal
5200 / 1943 / 251
Регистрация: 17.02.2013
Сообщений: 2,882
24.04.2015, 12:20 46
Цитата Сообщение от Витальич Посмотреть сообщение
ИМХО: проще то оно проще, но вопрос задал начинающий и таких изысков еще не знает
Изыски, это вот то, что VarleryS упомянул - целочисленное деление. Для знаковых целых существуют два разных целочисленных деления и это точно изыски. А вот &= 7 - это базовый прием, который надо впитывать сразу.

Вот, специально для ТС :
&= 7 обнуляет у числа все биты, кроме младших трех.
Т.е. если ты будешь после каждой операции с переменной делать над ней &=7, то ты по сути сделаешь так, как будьто в отношении данной переменной процессор 3-х битный, а не 8-и битный. И переменная трехбитная. И значения у нее только от 0 до 7.
Если ее увеличивать на единицу
count ++ ;
count &= 7 ;
то она будет по кругу нарезать
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ...
как будь-то она и на самом деле трехбитная.
А пусть тебе нужна четырехбитная переменная. Тогда после каждой операции над ней обнуляй у нее все биты, кроме младших 4-х. А это делается &=0xF . И тогда эта переменная будет иметь значения только от 0 до 0xF.
и при
count ++ ;
count &= 0xF ;
нарезать по кругу
0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F ...
0
MS24
11 / 11 / 2
Регистрация: 22.02.2012
Сообщений: 115
Завершенные тесты: 1
24.04.2015, 12:49 47
Цитата Сообщение от Ethereal Посмотреть сообщение
Вот, специально для ТС :
Рано мне кажется ТС лезть в такие дебри, но написанно все верно. Ну а вообще, имхо чем понятнее код - тем лучше.
0
Ethereal
5200 / 1943 / 251
Регистрация: 17.02.2013
Сообщений: 2,882
24.04.2015, 13:07 48
А вот изыски для ValeryS. Если ты делишь целые, то есть два способа округления частного - в сторону нуля или в меньшую сторону. Первое деление называется симметричным (symmetrical division). Второе с округлением по полу (floored division). Для положительных или беззнаковых чисел в сторону нуля - это и есть в меньшую сторону. Т.е. в этом случае разницы между делениями нет. Она есть только для знаковых отрицательных чисел. Так вот в Си деление симметричное. Потому-что математики считают такое деление правильным. И инструкция IDIV процессора 80x86 делит симметрично. Т.е. симметричное деление на персоналках еще и компилируется эффективно. А вот арифметический сдвиг вправо - это деление знаковых на 2^N с округлением по полу. Выделение младших бит числа по И - это тоже получение остатка от деления на 2^N с округлением по полу. Т.е. симметричное деление - это деление, правильное глазами математиков, а деление с округлением по полу - деление, правильное глазами программистов. И в этом споре математики когда-то взяли верх.
Правила с этими делениями такие :
Знак частного : ясен пень минус только если знаки делимого и делителя разные.
Знак остатка : для симметричного деления совпадает со знаком делимого, а для деления с округлением по полу - совпадает со знаком делителя.
Ну и еще раз - для беззнаковых и знаковых заведомо положительных чисел никаких таких заморочек нет. Потому-что без разницы.
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
24.04.2015, 15:00  [ТС] 49
Как объявить глобально переменные bool?При таком написании,как сообщении
Цитата Сообщение от MS24 Посмотреть сообщение
bool flag1;
bool flag2;
bool flag3;
bool flag4;
bool flag5;
выдаёт ошибку-Error:a_prog.c(18): '(' expected
0
Витальич
1274 / 1184 / 174
Регистрация: 02.12.2013
Сообщений: 4,886
24.04.2015, 15:19 50
Где то в коде скобки нет.
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
24.04.2015, 16:32  [ТС] 51
Не в этом дело.Дальше в коде,где встречается переменная flag1...5,пишет что неизвестная переменна
0
Voland_
1688 / 1033 / 97
Регистрация: 04.01.2010
Сообщений: 3,482
24.04.2015, 16:54 52
Цитата Сообщение от gubilon Посмотреть сообщение
Не в этом дело.
в этом, в этом. Поищите либо в коде этой функции, либо в присоединенных файлах директивой #include
PS: это часто раздражает, кстати. Когда ошибка где-нить в хидере, а компилятор в итоге показывает ошибку где-нибудь уже в сишном файле.
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
24.04.2015, 17:04  [ТС] 53
Вроде исправил код.Получилось так:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*****************************************************                        
Chip type           : ATmega16
Clock frequency     : 4,000000 MHz
*****************************************************/              
#include <mega16.h>                                      // библиотека ввода\вывода микроконтроллера
#include <delay.h>
#include <stdio.h>                                        // библиотека задержки
/* массив вариантов вкл. светотодиодов на порте С */
flash unsigned char arrLed[]= {0b00000001,0b00000011,0b00000111,0b00001111,0b00011111,0b00111111,0b01111111,0b11111111,
 0b01111111,0b00111111,0b00011111,0b00001111,0b00000111,0b00000011,0b00000001,0b00000000};
flash unsigned char arrLedO[]= {0b10000000,0b11000000,0b11100000,0b11110000,0b11111000,0b11111100,0b11111110,0b11111111,
 0b11111110,0b11111100,0b11111000,0b11110000,0b11100000,0b11000000,0b10000000,0b00000000};
flash unsigned char arrLedCH[]= {0b00000010,0b00001010,0b00101010,0b10101010,0b00101010,0b00001010,0b00000010,0b00000000,
0b00000010,0b00001010,0b00101010,0b10101010,0b00101010,0b00001010,0b00000010,0b00000000};
flash unsigned char arrLedNECH[]= {0b00000001,0b00000101,0b00010101,0b01010101,0b00010101,0b00000101,0b00000001,0b00000000,
0b00000001,0b00000101,0b00010101,0b01010101,0b00010101,0b00000101,0b00000001,0b00000000};
flash unsigned char arrLedS[]= {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000};
typedef enum {false = 0, true = !false} bool;
/* Установка параметров таймера */
bool flag1;
bool flag2;
bool flag3;
bool flag4;
bool flag5;
void presets(void)
{
  DDRB  = 0b00000000;       
  PORTB = 0b11111111;                                   // Port B initialization
  DDRC  = 0b11111111; 
  PORTC = 0b00000000;
    TCCR0=0x09;
    TCNT0=0x00;
    OCR0=0x64;
    TIMSK=0x02;
} 
/* Опрос кнопок */
unsigned char KeyGet()
{
unsigned char tmp=0;
if (!PINB.0==0){tmp |= 01;}
if (!PINB.1==0){tmp |= 02;}
if (!PINB.2==0){tmp |= 03;}
if (!PINB.3==0){tmp |= 04;}
if (!PINB.4==0){tmp |= 05;}
return tmp;
} 
/* Прерывание таймера */
interrupt [TIM0_COMP]void timer0_comp_isr(void)
{
 static unsigned char count = 0;
 if(flag1)
    { 
        PORTC = arrLed[count];
    }
if(flag2)
    { 
        PORTC = arrLedO[count];
    }
if(flag3)
    { 
        PORTC = arrLedCH[count];
    }
if(flag4)
    { 
        PORTC = arrLedNECH[count];
    }
if(flag5)
    { 
        PORTC = arrLedS[count];
    } 
count++;
 if(count >= 8)
 {
   count = 0;
 }
} 
void main(void)
{
presets();
#asm("sei")
while(1)
 {
    if(KeyGet() == 1)
    {
         flag1 = true;
         flag2=false;
         flag3=false;
         flag4=false;
         flag5=false;
    }
 
    if(KeyGet() == 2)
    {
         flag1 = false;
         flag2 = true;
         flag3 = false;
         flag4=false;
         flag5=false;         
    }
    if(KeyGet() == 3)
    {
         flag1 = false;
         flag2=false;
         flag3=true;
         flag4=false;
         flag5=false;         
    }
 
    if(KeyGet() == 4)
    {
         flag1 = false;
         flag2 = false;
         flag3 = false;
         flag4=true;
         flag5=false;         
    }
    if(KeyGet() == 5)
    {
         flag1 = false;
         flag2=false;
         flag3=false;
         flag4=false;
         flag5=true;         
    }
 }
 }
В протеусе работать не хочет.Диоды вообще не реагирует,а надо,чтоб при нажатии кнопки заработала заданная подпрограмма и работала,пока не нажмёшь другую кнопку.
0
MS24
11 / 11 / 2
Регистрация: 22.02.2012
Сообщений: 115
Завершенные тесты: 1
24.04.2015, 17:46 54
Цитата Сообщение от gubilon Посмотреть сообщение
typedef enum {false = 0, true = !false} bool;
Что это??? О_о

Добавлено через 4 минуты
В прерывание - то заходит? помигайте там светодиодом что ли что бы понять
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
24.04.2015, 18:20  [ТС] 55
По сайтам нашел такой код.Ничего не происходит
0
ValeryS
Модератор
7446 / 5638 / 716
Регистрация: 14.02.2011
Сообщений: 19,206
Завершенные тесты: 1
24.04.2015, 18:28 56
Цитата Сообщение от MS24 Посмотреть сообщение
Что это???
описание типа bool
не во всех компиляторах она определена
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
25.04.2015, 21:12  [ТС] 57
а в чём ошибка?

Добавлено через 5 часов 4 минуты
Цитата Сообщение от Витальич Посмотреть сообщение
1
2
3
4
5
6
7
unsigned char KeyGet()
{
unsigned char tmp;
if (PINB.0==0){tmp = 01;}
if (PINB.1==0){tmp = 02;}
return tmp;
}
Витальич,а какая роль переменной tmp в данной подпрограмме и какие значения она может принимать?

Добавлено через 21 час 5 минут
Нашел пробелы в коде.Вот конечный вариант программы(может кому-нибудь еще пригодиться).Единственное подредактировать скорость мигания светодиодов.Всем спасибо.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*****************************************************                        
Chip type           : ATmega16
Clock frequency     : 4,000000 MHz
*****************************************************/              
#include <mega16.h>                                      // библиотека ввода\вывода микроконтроллера
#include <delay.h>
#include <stdio.h>                                        // библиотека задержки
/* массив вариантов вкл. светотодиодов на порте С */
flash unsigned char arrLed[]= {0b00000001,0b00000011,0b00000111,0b00001111,0b00011111,0b00111111,0b01111111,0b11111111,
 0b01111111,0b00111111,0b00011111,0b00001111,0b00000111,0b00000011,0b00000001,0b00000000};
flash unsigned char arrLedO[]= {0b10000000,0b11000000,0b11100000,0b11110000,0b11111000,0b11111100,0b11111110,0b11111111,
 0b11111110,0b11111100,0b11111000,0b11110000,0b11100000,0b11000000,0b10000000,0b00000000};
flash unsigned char arrLedCH[]= {0b00000010,0b00001010,0b00101010,0b10101010,0b00101010,0b00001010,0b00000010,0b00000000,
0b00000010,0b00001010,0b00101010,0b10101010,0b00101010,0b00001010,0b00000010,0b00000000};
flash unsigned char arrLedNECH[]= {0b00000001,0b00000101,0b00010101,0b01010101,0b00010101,0b00000101,0b00000001,0b00000000,
0b00000001,0b00000101,0b00010101,0b01010101,0b00010101,0b00000101,0b00000001,0b00000000};
typedef enum {false = 0, true = 1} bool;
/* Установка параметров таймера */
bool flag1;
bool flag2;
bool flag3;
bool flag4;
bool flag5;
void presets(void)
{
  DDRB  = 0b00000000;       
  PORTB = 0b11111111;                            // Port B initialization
  PORTC=0x00;
  DDRC=0xFF;
  TCCR0=0x09;
  TCNT0=0x00;
  OCR0=0x64;
  TIMSK=0x02; 
} 
/* Опрос кнопок */
unsigned char KeyGet()
{
unsigned char tmp=0;
if (!PINB.0){tmp = 01;}
if (!PINB.1){tmp = 02;}
if (!PINB.2){tmp = 03;}
if (!PINB.3){tmp = 04;}
if (!PINB.4){tmp = 05;}
return tmp;
} 
/* Прерывание таймера */
interrupt [TIM0_COMP]void timer0_comp_isr(void)
{
 static unsigned char count = 0;
 if(flag1)
    { 
        PORTC = arrLed[count];
    }
if(flag2)
    { 
        PORTC = arrLedO[count];
    }
if(flag3)
    { 
        PORTC = arrLedCH[count];
    }
if(flag4)
    { 
        PORTC = arrLedNECH[count];
    }
if(flag5)
    { 
        PORTC = 0;
    } 
count++;
 if(count >= 16)
 {
   count = 0;
 }
} 
void main(void)
{
presets();
#asm("sei")
while(1)
 {
    if(KeyGet() == 1)
    {
         flag1 = true;
         flag2 = false;
         flag3 = false;
         flag4 = false;
         flag5 = false;
    }
 
    if(KeyGet() == 2)
    {
         flag1 = false;
         flag2 = true;
         flag3 = false;
         flag4 = false;
         flag5 = false;         
    }
    if(KeyGet() == 3)
    {
         flag1 = false;
         flag2 = false;
         flag3 = true;
         flag4 = false;
         flag5 = false;         
    }
 
    if(KeyGet() == 4)
    {
         flag1 = false;
         flag2 = false;
         flag3 = false;
         flag4 = true;
         flag5 = false;         
    }
    if(KeyGet() == 5)
    {
         flag1 = false;
         flag2 = false;
         flag3 = false;
         flag4 = false;
         flag5 = true;         
    }
 }
 }
0
MS24
11 / 11 / 2
Регистрация: 22.02.2012
Сообщений: 115
Завершенные тесты: 1
26.04.2015, 00:30 58
Цитата Сообщение от gubilon Посмотреть сообщение
Нашел пробелы в коде.Вот конечный вариант программы(может кому-нибудь еще пригодиться).Единственное подредактировать скорость мигания светодиодов.Всем спасибо.
Ну значит все заработало, можно поздравлять? )))
0
gubilon
1 / 1 / 0
Регистрация: 18.04.2015
Сообщений: 25
26.04.2015, 00:52  [ТС] 59
Конечно.Спасибо за помощь.Осталось объяснить преподу,как это работает)
0
26.04.2015, 00:52
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.04.2015, 00:52

Переключение четырех светодиодов (сдвиг) по кнопке
Добрый день. Требуется помощь в написании кода на Assembler. Задание...

Последовательное зажигание Пяти светодиодов
Всем привет! Загорелся идеей собрать световой меч, на пяти светодиодах, их суну...

Последовательное зажигание светодиодов на Arduino UNO
здравствуйте. нужна помощь. имеется arduino uno. нужно спрограммировать его...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
59
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru