Наконец-то дошли руки до этой няшки. Когда почитал даташит на 600 страниц, первый вопрос был - а это точно тинька? Периферия не очень богата - два обычных 16-битных таймера, один 16-ти битный RTC таймер, один 12-битный, АЦП 10 бит, ЦАП 8 бит с кучей внутренних референсных напряжений, оконный WDT. Ну и плюшки - 3-х уровневые прерывания, система событий, безумный блок CCL. Впрочем, те, кто программирует XMEGA, ничего нового не произошло - менно от этой линейки происходят новые тиньки нулевой и первой серии. Разве что порт программирования PDI превратился в UPDI. Ну давайте уже помОргаем светодиодиком. У меня на руках давно купленная в ЧиДе по дешману плата Xplained Mini - на ней и буду осваивать новые восьмибиточки))) На ней присутствует светодиод на порту PC0 и кнопка на порту PC5. Будем на кнопочку давить и ожидать, что светодиодик погаснет=) Давайте писать код. Определим константы: Код (C++): uint8_t const maskLED = 0b00000001; uint8_t const maskSwitch = 0b00100000; uint8_t const Switch = 5; Теперь напишем функцию, которая читает кнопку: Код (C++): uint8_t GetSwith (PORT_t volatile *switchPort, uint8_t mask) { return (switchPort->IN & mask); } Здесь все просто - читаем регистр IN порта и по маске отсекаем всё лишнее. Теперь функция поджига светика: Код (C++): void SetLEDPort (PORT_t volatile *ledPort, uint8_t value, uint8_t mask) { ledPort->OUT = ledPort->OUT & ~mask | value; } Здесь также по маске стираем значение порта и выставляем новое. Ну и главная функция Код (C++): int main(void) { PORT_t volatile *ledPort = &PORTC; PORT_t volatile *switchPort = &PORTC; ledPort->DIR = maskLED; while (1) { uint8_t value = (GetSwith(switchPort, maskSwitch) >> Switch); SetLEDPort(ledPort, value, maskLED); } } Т.к. кнопка и светодиод физически висят на разных битах, то смещением вправо на 5 бит мы значение кнопки ставим на место светодиода. И самое важное - для программирования необходим всего один проводок, не считая нулевого. По нему же работает внутрисхемная отладка. Красный квадратик в регистре IN - это я отпустил кнопку. Размер кода - 106 байт с оптимизацией O3. Скоро освоим таймер! А потом и АЦП. До новых ВСТРЕЧ!
Ой, что делается то??? Теория переходит к практике? @parovoZZ, на практике, кнопку без обработки дребезга, и светодиод освоил ! А я в свое время, года 4-е назад, наоборот, от ATxmega, тяжелого Atmel Studio, ASF и "чистого Си" с перешел на Ардуино. Периодически что-то небольшое для МК на Си пишу, а так под Ардуино, и всем доволен на 100%. Особенно если что-то под ESP писать. Не профессионально, а для себя . Быстро, очень надежно, и не накладно. И грузится намного быстрее.
И я тоже.К кодвижен обращаюсь редко если только по нужде.А Паровоз он же профессионал он серьезные вещи робит.Начинку для ЯРСов это не хвост собачий.
Скажи мне - чем отличается Код (C++): SPI0.CTRLA от Код (C++): SPI0_CTRLA Первое понятно - это поля структуры, второе - это классический адрес регистра. Но зачем была введена структура?
Вот Код (C++): typedef struct PORT_struct { register8_t DIR; /* Data Direction */ register8_t DIRSET; /* Data Direction Set */ register8_t DIRCLR; /* Data Direction Clear */ register8_t DIRTGL; /* Data Direction Toggle */ register8_t OUT; /* Output Value */ register8_t OUTSET; /* Output Value Set */ register8_t OUTCLR; /* Output Value Clear */ register8_t OUTTGL; /* Output Value Toggle */ register8_t IN; /* Input Value */ register8_t INTFLAGS; /* Interrupt Flags */ register8_t reserved_0x0A; register8_t reserved_0x0B; register8_t reserved_0x0C; register8_t reserved_0x0D; register8_t reserved_0x0E; register8_t reserved_0x0F; register8_t PIN0CTRL; /* Pin 0 Control */ register8_t PIN1CTRL; /* Pin 1 Control */ register8_t PIN2CTRL; /* Pin 2 Control */ register8_t PIN3CTRL; /* Pin 3 Control */ register8_t PIN4CTRL; /* Pin 4 Control */ register8_t PIN5CTRL; /* Pin 5 Control */ register8_t PIN6CTRL; /* Pin 6 Control */ register8_t PIN7CTRL; /* Pin 7 Control */ register8_t reserved_0x18; register8_t reserved_0x19; register8_t reserved_0x1A; register8_t reserved_0x1B; register8_t reserved_0x1C; register8_t reserved_0x1D; register8_t reserved_0x1E; register8_t reserved_0x1F; } PORT_t; Идея в чем - структура есть указатель адреса на физический адрес первого регистра - DIR. Смещение адреса поля структуры есть адрес реального регистра. Заданы они так: Код (C++): #define PORTA (*(PORT_t *) 0x0400) /* I/O Ports */ #define PORTB (*(PORT_t *) 0x0420) /* I/O Ports */ #define PORTC (*(PORT_t *) 0x0440) /* I/O Ports */ Также есть виртуальные порты ввода/вывода, которые есть "отображение" реальных портов, но в ОЗУ Код (C++): typedef struct VPORT_struct { register8_t DIR; /* Data Direction */ register8_t OUT; /* Output Value */ register8_t IN; /* Input Value */ register8_t INTFLAGS; /* Interrupt Flags */ } VPORT_t; Даташит утверждает, что прелесть в таких портах заключается в следующем Но можно обращаться и напрямую, по старинке: Код (C++): #define PORTA_DIR _SFR_MEM8(0x0400) #define PORTA_DIRSET _SFR_MEM8(0x0401) #define PORTA_DIRCLR _SFR_MEM8(0x0402) #define PORTA_DIRTGL _SFR_MEM8(0x0403) #define PORTA_OUT _SFR_MEM8(0x0404) #define PORTA_OUTSET _SFR_MEM8(0x0405) #define PORTA_OUTCLR _SFR_MEM8(0x0406) #define PORTA_OUTTGL _SFR_MEM8(0x0407) #define PORTA_IN _SFR_MEM8(0x0408) #define PORTA_INTFLAGS _SFR_MEM8(0x0409) #define PORTA_PIN0CTRL _SFR_MEM8(0x0410) #define PORTA_PIN1CTRL _SFR_MEM8(0x0411) #define PORTA_PIN2CTRL _SFR_MEM8(0x0412) #define PORTA_PIN3CTRL _SFR_MEM8(0x0413) #define PORTA_PIN4CTRL _SFR_MEM8(0x0414) #define PORTA_PIN5CTRL _SFR_MEM8(0x0415) #define PORTA_PIN6CTRL _SFR_MEM8(0x0416) #define PORTA_PIN7CTRL _SFR_MEM8(0x0417) Вот как-то так. В заголовочниках MSP430 примерно всё тоже самое.