roboforum.ru

Технический форум по робототехнике.

МикроКонтроллер AVR начинающим - общие вопросы

Re: МикроКонтроллеры начинающим - общие вопросы

Dmitryk1 » 03 дек 2008, 19:22

Уважаемые специалисты. Нашёл в интернете код, для подключения АВР к УСБ Чать кода - виндовая программа с драйвером, а часть - прошивка. В виндовой программе я разобрался и понял как изменять чтобы обрабатывать полученные сигналы, и чтобы закидывать свои сигналы в микроконтроллер. А вот с прошивкой оказалось для меня гораздо сложнее. Я никак не найду строк которые занимаются непосредственно отправкой и получением данных.

Возможно Вы сможете мне подсказать?
подозреваю, что процедура usbPoll() отвечает за приём данных. Которые складываются в определённый регистр. но не пойму в какой. А вот отправку вообще не смог найти :(

Ниже код с основным файлом прошивки ( без инклюдов) а при необходимости, ещё ниже всё вместе зазипованное, но без драйверов, скомпилиных приложений и хэлпов.
Код: Выделить всёРазвернуть
/* Name: main.c
* Project: PowerSwitch based on AVR USB driver
* Author: Christian Starkjohann
* Creation Date: 2005-01-16
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: main.c 523 2008-02-15 09:46:40Z cs $
*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>

#include "usbdrv.h"
#include "oddebug.h"
#include <util/delay.h>

/*
This module implements an 8 bit parallel output controlled via USB. It is
intended to switch the power supply to computers and/or other electronic
devices.

Application examples:
- Rebooting computers located at the provider's site
- Remotely switch on/off of rarely used computers
- Rebooting other electronic equipment which is left unattended
- Control room heating from remote
*/

#ifndef TEST_DRIVER_SIZE    /* define this to check out size of pure driver */

#define EEPROM_LOCATION (void *)37

static uchar    actionTimers[8];

/* This is the AT90S2313 version of the routine. Change for others. */
static void outputByte(uchar b)
{
    PORTB = (PORTB & ~0xfc) | (b & 0xfc);
    PORTD = (PORTD & ~0x30) | ((b << 4) & 0x30);
}

static uchar    computeTemporaryChanges(void)
{
uchar   i, status = 0, mask = 1;

    for(i=0;i<8;i++){
        if(actionTimers[i])
            status |= mask;
        mask <<= 1;
    }
    return status;
}

static void computeOutputStatus(void)
{
uchar   status = eeprom_read_byte(EEPROM_LOCATION) ^ computeTemporaryChanges();

    outputByte(status);
}

/* We poll for the timer interrupt instead of declaring an interrupt handler
* with global interrupts enabled. This saves recursion depth. Our timer does
* not need high precision and does not run at a high rate anyway.
*/
static void timerInterrupt(void)
{
static uchar    prescaler;
uchar           i;

    if(!prescaler--){
        prescaler = 8;  /* rate = 12M / 1024 * 256 * 9 */
        for(i=0;i<8;i++){
            if(actionTimers[i])
                actionTimers[i]--;
        }
        computeOutputStatus();
    }
}

USB_PUBLIC uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;
uchar           status = eeprom_read_byte(EEPROM_LOCATION);
static uchar    replyBuf[2];

    usbMsgPtr = replyBuf;
    if(rq->bRequest == 0){  /* ECHO */
        replyBuf[0] = rq->wValue.bytes[0];
        replyBuf[1] = rq->wValue.bytes[1];
        return 2;
    }
    if(rq->bRequest == 1){  /* GET_STATUS -> result = 2 bytes */
        replyBuf[0] = status;
        replyBuf[1] = computeTemporaryChanges();
        return 2;
    }
    if(rq->bRequest == 2 || rq->bRequest == 3){ /* SWITCH_ON or SWITCH_OFF, index = bit number */
        uchar bit = rq->wIndex.bytes[0] & 7;
        uchar mask = 1 << bit;
        uchar needChange, isOn = status & mask;
        if(rq->bRequest == 2){  /* SWITCH_ON */
            status |= mask;
            needChange = !isOn;
        }else{              /* SWITCH_OFF */
            status &= ~mask;
            needChange = isOn;
        }
        if(rq->wValue.bytes[0] == 0){   /* duration == 0 -> permanent switch */
            actionTimers[bit] = 0;
            eeprom_write_byte(EEPROM_LOCATION, status);
        }else if(needChange){   /* temporary switch: value = duration in 200ms units */
            actionTimers[bit] = rq->wValue.bytes[0];
        }
    }
    computeOutputStatus();
    return 0;
}

/* allow some inter-device compatibility */
#if !defined TCCR0 && defined TCCR0B
#define TCCR0   TCCR0B
#endif
#if !defined TIFR && defined TIFR0
#define TIFR    TIFR0
#endif

int main(void)
{
uchar   i;

    wdt_enable(WDTO_1S);
    odDebugInit();
    DDRD = ~(1 << 2);   /* all outputs except PD2 = INT0 */
    PORTD = 0;
    PORTB = 0;          /* no pullups on USB pins */
/* We fake an USB disconnect by pulling D+ and D- to 0 during reset. This is
* necessary if we had a watchdog reset or brownout reset to notify the host
* that it should re-enumerate the device. Otherwise the host's and device's
* concept of the device-ID would be out of sync.
*/
    DDRB = ~USBMASK;    /* set all pins as outputs except USB */
    computeOutputStatus();  /* set output status before we do the delay */
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    i = 0;
    while(--i){         /* fake USB disconnect for > 500 ms */
        wdt_reset();
        _delay_ms(2);
    }
    usbDeviceConnect();
    TCCR0 = 5;          /* set prescaler to 1/1024 */
    usbInit();
    sei();
    for(;;){    /* main event loop */
        wdt_reset();
        usbPoll();
        if(TIFR & (1 << TOV0)){
            TIFR |= 1 << TOV0;  /* clear pending flag */
            timerInterrupt();
        }
    }
    return 0;
}

#else   /* TEST_DRIVER_SIZE */

/* This is the minimum do-nothing function to determine driver size. The
* resulting binary will consist of the C startup code, space for interrupt
* vectors and our minimal initialization. The C startup code and vectors
* (together ca. 70 bytes of flash) can not directly be considered a part
* of this driver. The driver is therefore ca. 70 bytes smaller than the
* resulting binary due to this overhead. The driver also contains strings
* of arbitrary length. You can save another ca. 50 bytes if you don't
* include a textual product and vendor description.
*/
uchar   usbFunctionSetup(uchar data[8])
{
    return 0;
}

int main(void)
{
#ifdef PORTD
    PORTD = 0;
    DDRD = ~(1 << 2);   /* all outputs except PD2 = INT0 */
#endif
    PORTB = 0;          /* no pullups on USB pins */
    DDRB = ~USBMASK;    /* all outputs except USB data */
    usbInit();
    sei();
    for(;;){    /* main event loop */
        usbPoll();
    }
    return 0;
}

#endif  /* TEST_DRIVER_SIZE */

PowerSwitch.for forum.zip
полный архив исходников
(96.17 КиБ) Скачиваний: 34

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 03 дек 2008, 22:33

200% тут зарыто то что вы ищите.... #include "usbdrv.h"

Re: МикроКонтроллеры начинающим - общие вопросы

dm116 » 06 дек 2008, 19:19

Подскажите,как сделать так,чтобы при кратковременном нажатии кнопки выполнялась одна команда,а при нажатии и удержании более 3 сек-другая. ATMEGA16, CVAVR.

Re: МикроКонтроллеры начинающим - общие вопросы

rig » 06 дек 2008, 19:59

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

Re: МикроКонтроллеры начинающим - общие вопросы

dm116 » 06 дек 2008, 22:33

Ну тогда вопрос-как считать время для этого ? :oops:

Re: МикроКонтроллеры начинающим - общие вопросы

Vooon » 07 дек 2008, 00:31

Вы же в цикле опрашиваете кнопки?

Просто нужно сделать чтобы процедура обработки запускалась по отпусканию кнопки, а пока кнопка нажата увеличивать переменную.
Когда программа узнает, что кнопку отпустили, она проверяет эту переменную и в зависимости от ее значения (меньше трех секунд/больше) запускает нужную процедуру.

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 09 дек 2008, 20:00

ааа.. памагите загнать таймер 1 в меге 32 в 11-ти битный режим интересует конкретно использование ICR для указания вершины.. на любом языке)) главное биты... я не пойму либо меня кидают либо я туплю (((

Re: МикроКонтроллеры начинающим - общие вопросы

avr123.nm.ru » 09 дек 2008, 22:53

Duhas писал(а):ааа.. памагите загнать таймер 1 в меге 32 в 11-ти битный режим интересует конкретно использование ICR для указания вершины.. на любом языке)) главное биты... я не пойму либо меня кидают либо я туплю (((

Попробуй настроить мастером компилятора ICC - http://avr123.nm.ru/z6.htm
Наверняка получится. Или русский даташит на atmega посмотри http://avr123.nm.ru/02.htm

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 09 дек 2008, 23:03

да как бы мне и нерусский понятен на много процентов... но не хочет работать и все тут ... все остальные режимы настраиваются... а кодвижн ставить уж больно неохота.. пока что забил и оставил 10-ти битный...

Re: МикроКонтроллеры начинающим - общие вопросы

avr123.nm.ru » 09 дек 2008, 23:18

Duhas писал(а): кодвижн ставить уж больно неохота..

Я не CVAVR , а именно мастер ICC советую для настройки таймеров AVR !
У компилятора ICC в мастере все режимы каждого таймера наглядно показываются.

Изображение

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 09 дек 2008, 23:28

увы, на анлин я еще не пересел а трафа жалка... если не затруднит то не могли бы вы поставить фаст пвм топ = ICR.. хотя мне кажется что сабака зарыта где-то еще... ибо в даташите все оченб понятно что и куда писать.. но работать оно отказывается... притом на нескольких различных комбинациях...

Re: МикроКонтроллеры начинающим - общие вопросы

avr123.nm.ru » 09 дек 2008, 23:37

Duhas писал(а): если не затруднит то не могли бы вы поставить фаст пвм топ = ICR..


Вот все режимы с топ = ICR ...

Код: Выделить всёРазвернуть
//ICC-AVR application builder : 09.12.2008 22:32:03
// Target : M32
// Crystal: 4.0000Mhz

#include <iom32v.h>
#include <macros.h>

Режим 14    PWM fast, TOP=ICRn

//TIMER1 initialize - prescale:1
// WGM: 14) PWM fast, TOP=ICRn
// desired value: 15000Hz
// actual value: 15037,594Hz (0,3%)

TCCR1B = 0x00; //stop
TCNT1H = 0xFE; //setup
TCNT1L = 0xF7;
OCR1AH = 0x01;
OCR1AL = 0x09;
OCR1BH = 0x01;
OCR1BL = 0x09;
ICR1H  = 0x01;
ICR1L  = 0x09;
TCCR1A = 0x02;
TCCR1B = 0x19; //start Timer


Режим 8

//TIMER1 initialize - prescale:1
// WGM: 8) PWM phz freq correct, TOP=ICRn   
// desired value: 15000Hz
// actual value: 15037,594Hz (0,3%)

TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x7B;
OCR1AH = 0x00;
OCR1AL = 0x85;
OCR1BH = 0x00;
OCR1BL = 0x85;
ICR1H  = 0x00;
ICR1L  = 0x85;
TCCR1A = 0x00;
TCCR1B = 0x11; //start Timer


режим 10

//TIMER1 initialize - prescale:1
// WGM: 10) PWM phz correct, TOP= ICRn
// desired value: 15000Hz
// actual value: 15037,594Hz (0,3%)

TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x7B;
OCR1AH = 0x00;
OCR1AL = 0x85;
OCR1BH = 0x00;
OCR1BL = 0x85;
ICR1H  = 0x00;
ICR1L  = 0x85;
TCCR1A = 0x02;
TCCR1B = 0x11; //start Timer

режим 12

//TIMER1 initialize - prescale:1
// WGM: 12) CTC, TOP=ICRn
// desired value: 15000Hz
// actual value: 15037,594Hz (0,3%)

TCCR1B = 0x00; //stop
TCNT1H = 0xFE; //setup
TCNT1L = 0xF7;
OCR1AH = 0x01;
OCR1AL = 0x09;
OCR1BH = 0x01;
OCR1BL = 0x09;
ICR1H  = 0x01;
ICR1L  = 0x09;
TCCR1A = 0x00;
TCCR1B = 0x19; //start Timer

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 09 дек 2008, 23:50

ну с вашими параметрами почти работает.. ибо не превышает 10 бит... но вместо фаст пвм идет именно phase correct... считает до максимума и назад.... я начинаю грешить на авр студию... как будет возможность обновлюсь...
кстати запись регистров TCNT и OCR1xx при инициализации попахивает шаманством.. или я чего-то не понимаю... но ШИМ у мну всегда работал )

Re: МикроКонтроллеры начинающим - общие вопросы

avr123.nm.ru » 09 дек 2008, 23:57

Duhas писал(а):ну с вашими параметрами почти работает.. ибо не превышает 10 бит... но вместо фаст пвм идет именно phase correct... считает до максимума и назад.... я начинаю грешить на авр студию...

ИМХО лучше 4 Мб VMLAB скачать ! http://avr123.nm.ru

А про 14 режим написано именно "ФАСТ".

Кстати в АСМе viewtopic.php?f=2&t=4705
вы писали вместо:

TCCR1A = 0x02;
TCCR1B = 0x19; //start Timer

вот так:

TCCR1A = 0xA2;
TCCR1B = 0x19; //start Timer

Re: МикроКонтроллеры начинающим - общие вопросы

Duhas » 10 дек 2008, 00:20

угу... ибо в битах это 0b10100010
где старшие 1010 это выбор сброса пинов по совпадению и установки по вершине... при нулях ведь выхода с таймера в порт нет вообще


Rambler\'s Top100 Mail.ru counter