Я считаю, что Arduino - это по-настоящему хорошее начало в микроэлектронике. Но если вы хотите сделать что-то профессиональное, то вам следует использовать Atmel Studio.
Перейдем к комплектующим, используемые в нашей статье, для того, чтобы понять как работает Atmel Studio:
- Микрочип ATtiny85 × 1
- Коннекторы (10x2) × 1
- Перемычки (общие) × 1
Также необходимо программное обеспечение:
- Atmel Studio 7 (от Microchip)
- Atmel ICE программатор (от Microchip)
Я люблю использовать Arduino, но уже пора перейти к созданию загрузчиков и других программ, без загрузчика Arduino. Если вы когда-либо видели программное обеспечение устройства TV-Be-gone, то заметили, что загрузчик Arduino на нем отсутствует. Если вы понимаете Arduino, вы это тоже поймете.
Скачать Atmel Studio 7 можно на официальном сайте по этой ссылке, а также там вы можете купить программатор Atmel ICE avr.
Многие любители электроники используют сайт digikey.com для покупки такого рода комплектующих. Также сразу остановимся на распиновке Atmel ICE:
Все детали мы соединяем соответственно таким образом:
Чип <-> Коннектор
PB1 <-> Pin1
PB0 <-> Pin4
PB5 <-> Pin5
PB2 <-> Pin3
GND <-> GND
VCC <-> VCC
При программировании чипа необходимо питать его автономным источником питания. ICE не питает чип, который вы программируете. Если вы хотите узнать больше о чипе, который вы используете, вы можете перейти к Технической спецификации и прочитать о плавких предохранителях и регистрах, которые есть у чипа и как его использовать с примерами программ на C и машинном языке. Техническую спецификацию ATtiny85 можно посмотреть по этой ссылке.
В ATtiny85, чтобы сделать пин ввода/вывода, нужно настроить три регистра. Регистры похожи на выключатель света, который включает и выключает функции на чипсете. Регистр направления данных (DDRx) сообщает микросхеме, являются ли выводы входными или выходными. Если вы установите пин, который вы хотите на 1, то он будет выходным для DDRx, если 0 - входным. Для ATtiney85 этот регистр называется DDRB. Регистр PORTx - пин, который хотите использовать, управлять внешней схемой. Если пин настроен на вход, то состояние пина может быть прочитано МК в регистре PINx.
Как сдвинуть бит?
Можно использовать << или >>, первый - битовый сдвиг влево, а другой - битовый сдвиг вправо. Поэтому, для бинарного 0b00000010, вы должны сделать 1 << 2. В программе вы найдете _BV() или (1 << PB2). Также стоит сказать, что есть and, or, или xor. Всё будет выглядеть примерно так:
OR ( | ) 10101 | 00110 = 10111 AND ( & ) 10101 & 00110 = 00100 XOR ( ^ ) 10101 ^ 00110 = 10011 NOT ( ~ ) ~00110 = 11001
Вернемся к Arduino. МК имеет открытый исходный код и не имеет защиты, а ведь что если вы захотите сделать проект, который вы хотели бы продать широким массам. AVR имеет предохранители, которые вы можете установить для блокировки чипа, что не позволит загрузить hex файл на этот чип. Это называется блокировкой битов.
Но давайте перейдем к программированию. Ниже все необходимые примеры.
Пример кода AVR № 1 (C/C ++)
#include <avr/io.h> #include <util/delay.h> int main (void) { DDRB = 0b00000010; //this is the Data Direction Reg // with one pin on DDRB set to an output while (1) { PORTB = 0b00000010; //turn pin on with PORTB with set bit 1 _delay_ms(20); //delay 20ms PORTB = 0b00000000; //turn pin off with PORTB with set bit 0 _delay_ms(20); } return 0; }
Пример кода AVR № 2 (C/C ++)
#include <avr/io.h> #include <util/delay.h> #define LED PB0 #define LED_DDR DDRB #define LED_PORT PORTB #define DELAYTIME 200 #define setBit(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) #define clearBit(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) #define toggleBit(sfr, bit) (_SFR_BYTE(sfr) ^= (1 << bit)) int main(void) { // Init setBit(LED_DDR, LED); /* set LED pin for output */ // Mainloop while (1) { setBit(LED_PORT, LED); _delay_ms(DELAYTIME); clearBit(LED_PORT, LED); _delay_ms(DELAYTIME); } return 0; /* end mainloop */ }
Пример кода AVR № 3 (C/C ++)
// POV toy demo framework // // ------- Preamble -------- // #include <avr/io.h> #include <util/delay.h> // -------- Functions --------- // void POVDisplay(uint8_t oneByte) { PORTB = oneByte; _delay_ms(2); } int main(void) { // -------- Inits --------- // DDRB = 0xff; /* Set up all of LED pins for output */ // ------ Event loop ------ // while (1) { /* mainloop */ POVDisplay(0b00001110); POVDisplay(0b00011000); POVDisplay(0b10111101); POVDisplay(0b01110110); POVDisplay(0b00111100); POVDisplay(0b00111100); POVDisplay(0b00111100); POVDisplay(0b01110110); POVDisplay(0b10111101); POVDisplay(0b00011000); POVDisplay(0b00001110); PORTB = 0; _delay_ms(10); } /* end mainloop */ return 0; }
Пример код
/* Standard Macros */ /* You can totally get by without these, but why? */ /* Make sure we've already got io / sfr / pindefs loaded */ #ifndef _AVR_IO_H_ #include <avr/io.h> #endif /* Reminder: the following useful bit-twiddling macros are always included in avr/sfr_defs.h, which is called from avr/io.h bit_is_set(sfr, bit) bit_is_clear(sfr, bit) loop_until_bit_is_set(sfr, bit) loop_until_bit_is_clear(sfr, bit) */ /* Define up the full complement of bit-twiddling macros */ #define BV(bit) (1 << bit) #define set_bit(sfr, bit) (_SFR_BYTE(sfr) |= BV(bit)) // old sbi() #define clear_bit(sfr, bit) (_SFR_BYTE(sfr) &= ~BV(bit)) // old cbi() #define toggle_bit(sfr, bit) (_SFR_BYTE(sfr) ^= BV(bit))
Код определения пинов
#define LED_PORT PORTB #define LED_PIN PINB #define LED_DDR DDRB #define LED0 PB0 #define LED1 PB1 #define LED2 PB2 #define LED3 PB3 #define LED4 PB4 #define LED5 PB5 #define LED6 PB6 #define LED7 PB7 #define BUTTON_PORT PORTD #define BUTTON_PIN PIND #define BUTTON_DDR DDRD #define BUTTON PD2 #define BUTTON2 PD3 #define BUTTON3 PD4 #define SPEAKER PD6 /* OC0A */ #define SPEAKER_PORT PORTD #define SPEAKER_PIN PIND #define SPEAKER_DDR DDRD #define ANTENNA PD5 /* OC0B */ #define ANTENNA_PORT PORTD #define ANTENNA_PIN PIND #define ANTENNA_DDR DDRD #define MODULATION PD3 /* OC2B */ #define MODULATION_PORT PORTD #define MODULATION_PIN PIND #define MODULATION_DDR DDRD #define LIGHT_SENSOR PC0 /* ADC0 */ #define LIGHT_SENSOR_PORT PORTC #define LIGHT_SENSOR_PIN PINC #define LIGHT_SENSOR_DDR DDRC #define CAP_SENSOR PC1 /* ADC1 */ #define CAP_SENSOR_PORT PORTC #define CAP_SENSOR_PIN PINC #define CAP_SENSOR_DDR DDRC #define PIEZO PC2 /* ADC2 */ #define PIEZO_PORT PORTC #define PIEZO_PIN PINC #define PIEZO_DDR DDRC #define POT PC3 /* ADC3 */ #define POT_PORT PORTC #define POT_PIN PINC #define POT_DDR DDRC // SPI and I2C serial mode defines #define SPI_SS PB2 #define SPI_SS_PORT PORTB #define SPI_SS_PIN PINB #define SPI_SS_DDR DDRB #define SPI_MOSI PB3 #define SPI_MOSI_PORT PORTB #define SPI_MOSI_PIN PINB #define SPI_MOSI_DDR DDRB #define SPI_MISO PB4 #define SPI_MISO_PORT PORTB #define SPI_MISO_PIN PINB #define SPI_MISO_DDR DDRB #define SPI_SCK PB5 #define SPI_SCK_PORT PORTB #define SPI_SCK_PIN PINB #define SPI_SCK_DDR DDRB #define I2C_SDA PC4 #define I2C_SDA_PORT PORTC #define I2C_SDA_PIN PINC #define I2C_SDA_DDR DDRC #define I2C_SCL PC5 #define I2C_SCL_PORT PORTC #define I2C_SCL_PIN PINC #define I2C_SCL_DDR DDRC
На этом всё.