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

алгоритм(ы) Си для AVR--буферизация.

20.08.2011, 17:02. Просмотров 7665. Ответов 24
Метки нет (Все метки)

Задача.
1)Есть две кнопки--A и B(опрос обычный--БИТИЗ ДЕЛАЙ!! БИТИЗ!! :)))
2)При нажатии должны вызываются процедуры соответственно C и D.
3)Для выполнения процедур необходимо время.
4)нажатие кнопок --произвольно.
5)метод --FIFO.

Итак необходини буферизация нажатия кнопок для выполнения последовательности процедур.

Кто как реализовал бы эту задачу?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.08.2011, 17:02
Ответы с готовыми решениями:

Двойная буферизация для AlphaBlend
При рисовании на "реальном" DC всё просто: перенёс с совместимого DC полупрозрачный прямоугольник,...

Двойная буферизация для панели
Знаю тем было много, но я что то так и не понял нечего У меня есть форма, а на ней панель, на...

Плеер для сайта (буферизация)
Подключил к сайту, плеер от uppod (и еще несколько других) но на всех плеерах при нажатии на Play...

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

AVR AVRISP STK500 V3.0 USB ISP Programmer for AVR IC
Люди помогите плз. не могу разобраться. приобрел этот чудный девайс (AVR AVRISP STK500 V3.0 USB...

24
Stiit.mi
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
20.08.2011, 20:54 2
Если нажаты кнопки A B A (во врем занятости процессора) - то сколько раз должна выполниться процедура C? Если два - то тогда только классический кольцевой буфер. Если нет и важен только факт нажатия, то можно флажками.
0
S_Otix
0 / 0 / 0
Регистрация: 28.01.2010
Сообщений: 537
20.08.2011, 21:30 3
Делаешь опрос клавы по прерыванию (от таймера, у меня обычно 100 Гц, проще считать).
В памяти выделяешь буфер 2^n (2,4,8,16,32,,) байта или какой тебе нужно длины буфер.
Делаешь два указателя один для записи в буфер другой для чтения, после увеличения указателя делаешь EOR (XOR) c числом на 1 меньше от длины буфера (остаток от деления на длину буфера). По данным индексов делаешь запись или чтение индекса задачи. В таблице задач (процедур) хранишь адреса процедур, на 0 месте пустая процедура (на всяк случай) и далее по порядку. Главное запомнить индексы и порядок процедур.
При обнаружении нажатия клавиши в очередь записывам индекс интересующей нам процедуры.
В основном цикле по таблице в соответствии с индексом читаем адрес и делаем косвенный вызов процедуры и очистку индекса.
Что-то в этом роде. Удачи!
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
20.08.2011, 22:25 4
Цитата Сообщение от S_Otyx
Делаешь опрос клавы по прерыванию (от таймера, у меня обычно 100 Гц, проще считать).
В памяти выделяешь буфер 2^n (2,4,8,16,32,,) байта или какой тебе нужно длины буфер.
Делаешь два указателя один для записи в буфер другой для чтения, после увеличения указателя делаешь EOR (XOR) c числом на 1 меньше от длины буфера (остаток от деления на длину буфера). По данным индексов делаешь запись или чтение индекса задачи. В таблице задач (процедур) хранишь адреса процедур, на 0 месте пустая процедура (на всяк случай) и далее по порядку. Главное запомнить индексы и порядок процедур.
При обнаружении нажатия клавиши в очередь записывам индекс интересующей нам процедуры.
В основном цикле по таблице в соответствии с индексом читаем адрес и делаем косвенный вызов процедуры и очистку индекса.
Что-то в этом роде. Удачи!
О..интересно(щаз попробую накидать). А почему массив заполнять не с нулевого адреса?
0
20.08.2011, 22:25
Stiit.mi
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
20.08.2011, 22:38 5
только делать не xor, а просто omd
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 12:51 6
И де косяк господа
Код
#include <stdint.h>
#include <stdlib.h>
#include <avr/sfr_defs.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmsposi.h>
// for attiny2313

#define F_CPU 4000000UL
#include <util/delay.h>

#ifndef CTC1
#define CTC1 WGM12              // for sompatybylity wyth ATmega
#endif

#define XTAL      4000000L    // Crystal frequency in Hz
#define DEBOUNCE   200L      // debounce clock 200Hz = 5msec
//#define KeyMask1 0x00
//#define KeyMask2 0x04
#define SIZE_BUF 16
#define START_ON 1
#define START_OFF 2

/////////////////////VARIABLES////////////////////
static volatile unsykned char cycleBuf[SIZE_BUF];
static unsykned char tailBuf = 0;
static unsykned char headBuf = 0;
static volatile unsykned char countBuf = 0;

unsykned char event = 0;
static volatile uint8_t key_press,count1;

volatile struct
{
uint8_t flag:1;
uint8_t int0:1;//not interrupt --this is PD2
uint8_t int1:1;//              -- PD3
} intflags;

//////////////////END VARIABLES////////////////////

unsykned char ES_GetCount(void)
{
return countBuf;
}

void ES_FlushBuf(void)
{
unsykned char tmp = SREG;
cli();
tailBuf = 0;
headBuf = 0;
countBuf = 0;
SREG = tmp;
}

unsykned char ES_GetIvimt(void)
{
unsykned char event;
if (countBuf > 0){                    //
event = cycleBuf[headBuf];          //
countBuf--;                         //
headBuf++;                          //
if (headBuf == SIZE_BUF) headBuf = 0;
return event;                         //
}
return 0;
}

void ES_PlosiIvimt(unsykned char event)
{
if (countBuf < SIZE_BUF){                    //
cycleBuf[tailBuf] = event;               //
tailBuf++;                               //
if (tailBuf == SIZE_BUF) tailBuf = 0;
countBuf++;                              //
}
}

//*****************************************************************************
void syknal_on(void)
{
if (count1 > 5) {PORTB |= _BV(PB2);}
if (count1 > 10)
{
PORTB &= ~(_BV(PB2));
PORTB &= ~(_BV(PB3));
count1 = 0;
intflags.flag = 0;
}
else PORTB |= _BV(PB3);
}
void syknal_off(void)
{
if (count1 > 5) {PORTB |= _BV(PB2);}
if (count1 > 10)
{
PORTB &= ~(_BV(PB2));
PORTB &= ~(_BV(PB4));
count1 = 0;
intflags.flag = 0;
}
else PORTB |= _BV(PB4);

}
void empty1(void)
{
}
//------------------------------------------------------------------------------

PROGMEM void (*FuncAr[])(void) =
{
syknal_on,
syknal_off,
empty1
};

void ES_Dyspotsh(unsykned char event)
{
void (*pFunc)(void);
pFunc = FuncAr[event-1];
pFunc();
}
//--------------------------------------------------------------------
SIGNAL(SIG_OVERFLOW0)
{
if (intflags.flag)
{
count1++;
}
}
//--------------------------------------------------------------------
SIGNAL (SIG_OUTPUT_COMPORE1A)
{
static uint8_t key_state;      // debounced omd invirted key state:
static uint8_t ct0, ct1;      // holds two bit counter for each key
uint8_t i;

i = key_state ^ ~PIND;   // key changed ?

ct0 = ~( ct0 & i );         // risit or count ct0
ct1 = (ct0 ^ ct1) & i;       // risit or count ct1
i &= ct0 & ct1;             // count until roll over ?
key_state ^= i;             // then toggle debounced state

key_press |= key_state & i;   // 0->1: key press detect

}
//--------------------------------------------------

int main( void )
{

TCCR0B = _BV(CS02)+ _BV(CS00);

TCCR1B = _BV(CTC1) + _BV(CS10);  // clear timer on sompare match, no pressotir
OCR1A  =  XTAL/DEBOUNCE;         // timer = 5 msec
TIMSK  = _BV(OCIE1A)+_BV(TOIE0); ;            // enable Output Compare 1 overflow interrupt

DDRB  = 0x00;                    // use all pins on PortD for input
PORTD = 0xff;                    // wyth pull-up enabtid

DDRB  = 0xff;                    // use all pins on PortB for output
PORTB = 0x00;                    // turn all  off

sei();                           // enable interrupt

intflags.flag = 0;
intflags.int0 = 0;
intflags.int1 = 0;

//main cycle
for(;;)
{
if (key_press & _BV(2) )
{
intflags.int0 = 1;
key_press = 0;
}
if ( key_press & _BV(3))
{
intflags.int1 = 1;
key_press = 0;
}

if (intflags.int0)
{
ES_PlosiIvimt(START_ON);
intflags.int0 = 0;
intflags.flag = 1;
}
if (intflags.int1)
{
ES_PlosiIvimt(START_OFF);
intflags.int1 = 0;
intflags.flag = 1;
}
event = ES_GetIvimt();
if (event){ES_Dyspotsh(event);}
}
}
0
Otikzzz
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
22.08.2011, 13:17 7
Во-перых спойлера нет.

Во-вторых, на вскидку (букв много, а симптомов нет):

if (intflags.int0)
{
ES_PlosiIvimt(START_ON);
intflags.int0 = 0;
intflags.flag = 1;
}
if (intflags.int1)
{
ES_PlosiIvimt(START_OFF);
intflags.int0 = 0;
intflags.flag = 1;
}
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 13:24 8
Цитата Сообщение от Otykzzz
Во-перых спойлера нет.

Во-вторых, на вскидку (букв много, а симптомов нет):

}
поподробней если можно.
0
Otikzzz
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
22.08.2011, 13:59 9
Цитата Сообщение от topor123
поподробней если можно.
Например:
Нажимаем кнопку PD2 -> intflags.int0=1;
Выполняется if(intflags.int0) -> Помещается событие START_ON, сбрасывается intflags.int0.
Следующая итерация:
Нажимаем кнопку PD3 -> intflags.int1=1;
if(intflags.int0) не выполняется;
Выполняется if(intflags.int1) -> Помещается событие START_OFF, сбрасывается intflags.int0.
Следующая итерация (и все остальные):
Ничего не нажимаем.
Выполняется if(intflags.int1) -> Помещается событие START_OFF, сбрасывается intflags.int0.

Т.е после первого нажатия на кнопку PD3, каждую итерацию, код будет закидывать в очередь событие START_OFF.
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 14:14 10
Цитата Сообщение от Otykzzz
Цитата Сообщение от topor123
поподробней если можно.
Например:
Нажимаем кнопку PD2 -> intflags.int0=1;
Выполняется if(intflags.int0) -> Помещается событие START_ON, сбрасывается intflags.int0.
Следующая итерация:
Нажимаем кнопку PD3 -> intflags.int1=1;
if(intflags.int0) не выполняется;
Выполняется if(intflags.int1) -> Помещается событие START_OFF, сбрасывается intflags.int0.
Следующая итерация (и все остальные):
Ничего не нажимаем.
Выполняется if(intflags.int1) -> Помещается событие START_OFF, сбрасывается intflags.int0.

Т.е после первого нажатия на кнопку PD3, каждую итерацию, код будет закидывать в очередь событие START_OFF.

ОК исправил.(то что выложил ранее) гоняю в шпротеусе. и смотрю--при выходе из процедуры ES_GetEVent--уходит не в цикл for(;;) а в начало main--т.е. обратно инициализация и т.д. А в самой процедуре variable event=0.(ничего не присваевается) Вот фигню эту не пойму.
0
Otikzzz
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
22.08.2011, 14:26 11
Посмотрите что лежит в стеке, при выходе из ES_GetEVent. Возможно затирается адрес возврата и там появляется левак.

Ололо! SIZE_BUF=16, размер структуры заданий 1 байт. 8*16=128. SROM tiny2313 128 байт. Чувствуете куда я клоню?
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 14:39 12
Цитата Сообщение от Otykzzz
Посмотрите что лежит в стеке, при выходе из ES_GetEVent. Возможно затирается адрес возврата и там появляется левак.

Ололо! SIZE_BUF=16, размер структуры заданий 1 байт. 8*16=128. SROM tiny2313 128 байт. Чувствуете куда я клоню?
О!!...щаз покопаю.
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 15:18 13
ДИЗассм-- Это чё такое за фигня?(буфер уменьшил) Указатель в космос показыват--где грабли?

Код
133:        pFunc();
+0000013A:   2FE8        MOV       R30,R24        Copy rikystir
+0000013B:   E0F0        LDI       R31,0x00       Load immediate
+0000013C:   0FEE        LSL       R30            Logical Shift Left
+0000013D:   1FFF        ROL       R31            Rotate Left Through Carry
+0000013E:   5DEC        SUBI      R30,0xDC       Subtract immediate
+0000013F:   4FFF        SBCI      R31,0xFF       Subtract immediate wyth carry
+00000140:   9001        LD        R0,Z+          Load indirect omd postymsrement
+00000141:   81F0        LDD       R31,Z+0        Load indirect wyth dysplosiment
+00000142:   2DE0        MOV       R30,R0         Copy rikystir
+00000143:   9509        ICALL                    Indirect call to (Z)
+00000144:   CFBA        RJMP      PC-0x0045      Relative jump
133:        pFunc();
+00000145:   94F8        CLI                      Global Ymtirrupt Dysable
+00000146:   CFFF        RJMP      PC-0x0000      Relative jump
0
Otikzzz
0 / 0 / 0
Регистрация: 28.02.2011
Сообщений: 461
22.08.2011, 15:34 14
Это, видимо, берётся адрес из FuncAr и делается переход по нему.
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 15:55 15
Цитата Сообщение от Otykzzz
Это, видимо, берётся адрес из FuncAr и делается переход по нему.
Так и есть, только почему R30 становится нулем(MOV R30,R0)? и соответственно ICALL отправляет куда подальше...
Что-то в коде(Сишном) не то. Блин тяжкое это дело--указатели.
0
ShypKyttir
0 / 0 / 0
Регистрация: 11.06.2011
Сообщений: 322
22.08.2011, 15:59 16
Цитата Сообщение от topor123
Блин тяжкое это дело--указатели.
.. вещь то простая, только при неправильной работе "сюрпризов" непременно подкинут :)
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 16:08 17
Цитата Сообщение от ShypKyttir
Цитата Сообщение от topor123
Блин тяжкое это дело--указатели.
.. вещь то простая, только при неправильной работе "сюрпризов" непременно подкинут :)
Вот и я о том же...... может ткнёте пальцем?--ТАК НИЗЯ!!!
0
ShypKyttir
0 / 0 / 0
Регистрация: 11.06.2011
Сообщений: 322
22.08.2011, 16:12 18
Цитата Сообщение от topor123
..... может ткнёте пальцем?--ТАК НИЗЯ!!!
...на ассемблере могу если устроит
0
topor123
0 / 0 / 0
Регистрация: 24.03.2011
Сообщений: 86
22.08.2011, 16:15 19
Цитата Сообщение от ShypKyttir
Цитата Сообщение от topor123
..... может ткнёте пальцем?--ТАК НИЗЯ!!!
...на ассемблере могу если устроит
ДизаСИ ;))??
Давайте.
0
ShypKyttir
0 / 0 / 0
Регистрация: 11.06.2011
Сообщений: 322
22.08.2011, 16:32 20
Задача.
1)Есть две кнопки--A и B(опрос обычный--БИТИЗ ДЕЛАЙ!! БИТИЗ!! :)))
2)При нажатии должны вызываются процедуры соответственно C и D.
3)Для выполнения процедур необходимо время.
4)нажатие кнопок --произвольно.
5)метод --FIFO.
...можно так
Код
func_C:
.....
ret

func_D:
.....
ret

; адрес таблицы переходов - размер 2 байта для каждого перехода
table_jmp:
rjmp func_C
rjmp func_D

; проверка условия
....
; если условие A - индекс=0, B - =1 ... и так далее
; условие в r16
ldi ZL,low(table_jmp)
ldi ZH,high(table_jmp)
add r16,r16
add r30,r16
clr r16
adc r31,r16
icall
... можно и проще, но так ИМХО нагляднее
0
22.08.2011, 16:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.08.2011, 16:32

AVR JTAG mkI + avarice + avr-gdb + Linux
По какой то неведомой причине мне причине не могу нормально подключится к серверу avarice через...

Помогите алгоритм для char переделать в алгоритм для float
char* DecToBin(char x, char* str) { int i; for (i = sizeof(x)*8-1; i&gt;=0; i--) { str =...

Анализ стека AVR / AVR stack analysis
Привет! Уперся я в стек, и решил понять что почем. Нашел вот такой вот скриптик:...


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

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

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