Obsah

Atmel AVR

První kroky - programátor

avrdude
avrdude -c usbasp -p atmega8

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: error: programm enable: target doesn't answer. 1 
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.
# avrdude -c usbasp -p atmega8

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9307

avrdude: safemode: Fuses OK (E:FF, H:D9, L:E1)

avrdude done.  Thank you.
/etc/udev/rules.d/99-USBasp.rules 
# Set Group for USBasp
SUBSYSTEM=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", GROUP="djbuldog"

Kompilace

Atmel studio

Title: usbasp ATmega8
Command: B:\downloads\avr\avrdude.exe
Arguments: -c usbasp -p atmega8 -U flash:w:$(TargetDir)$(TargetName).hex:i 

[x] Use Output window

Linux

avr-libc
Makefile
MCU=atmega8a
AVRDUDEMCU=atmega8
CC=avr-gcc
OBJCOPY=avr-objcopy
PROJECT=pokus1
CFLAGS=-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues
 
# add simulavr and gtkvawe
 
all: $(PROJECT).hex $(PROJECT).bin
 
$(PROJECT).hex : $(PROJECT).elf
        $(OBJCOPY) -R .eeprom -O ihex $(PROJECT).elf $(PROJECT).hex 
 
$(PROJECT).bin : $(PROJECT).elf
        $(OBJCOPY) -R .eeprom -O binary $(PROJECT).elf $(PROJECT).bin
 
$(PROJECT).elf : $(PROJECT).o
        $(CC) $(CFLAGS) -o $(PROJECT).elf -Wl,-Map,$(PROJECT).map $(PROJECT).o
 
$(PROJECT).o : $(PROJECT).c
        $(CC) $(CFLAGS) -c $(PROJECT).c
 
load: $(PROJECT).hex
        #uisp -dlpt=/dev/parport0 --erase --upload --verify if=$(PROJECT).hex -dprog=dapa  -v=3 --hash=12
        avrdude -c usbasp -p $(AVRDUDEMCU) -U flash:w:$(PROJECT).hex:i
 
simulate: $(PROJECT).bin
        simulavr -d $(AVRDUDEMCU) -P simulavr-disp $(PROJECT).bin
 
clean:
        rm -f *.o *.map *.elf *.hex *.bin

Ladění

avr-gdb
simulavr
avr-gdb
(gdb) file pokus.elf
(gdb) target remote localhost:1212
(gdb) load
devsupp.c:332: MESSAGE: attach: IO Reg 'PIND' at 0x0030: created
devsupp.c:316: MESSAGE: attach: IO Reg 'DDRD' at 0x0031: ref = 0x0030
devsupp.c:316: MESSAGE: attach: IO Reg 'PORTD' at 0x0032: ref = 0x0030
devsupp.c:332: MESSAGE: attach: IO Reg 'PINC' at 0x0033: created
devsupp.c:316: MESSAGE: attach: IO Reg 'DDRC' at 0x0034: ref = 0x0033
devsupp.c:316: MESSAGE: attach: IO Reg 'PORTC' at 0x0035: ref = 0x0033
devsupp.c:332: MESSAGE: attach: IO Reg 'PINB' at 0x0036: created
devsupp.c:316: MESSAGE: attach: IO Reg 'DDRB' at 0x0037: ref = 0x0036
devsupp.c:316: MESSAGE: attach: IO Reg 'PORTB' at 0x0038: ref = 0x0036
(gdb) x/t 0x800035
0x800035:	00100000

Test rozsvěcování LED diody

DC Current per I/O Pin ....................................... 40.0mA
DC Current V CC and GND Pins................................. 300.0mA
ledtest.c
1  #include <avr/io.h>
2  #include <util/delay.h>
3 
4  int main(void)
5  {
6    DDRB |= (1 << PINB0);
7    PORTB &= ~(1 << PINB0);
8	
9    while(1)
10   {
11     _delay_ms(1000);
12     PORTB ^= (1 << PINB0);	
13   }
14 }

Test funkce Hall senzoru

Tlačítko

Jednoduché tlačítko

Matice

Test ovládání LED diod tlačítkem

led-switch.c
#include <avr/io.h>
#include <util/delay.h>
 
#define UP	0
#define DOWN	1
 
int main(void)
{
 
	/* Init LEDs */
	DDRD |= (1 << PIND6);
	DDRD |= (1 << PIND7);
	DDRB |= (1 << PINB0);
 
	/* Init push button */
	DDRC &= ~(1 << PINC5);
	PORTC |= (1 << PINC5);
 
	uint8_t active=0;
	uint8_t direction=DOWN;
	uint8_t btn_last=1;
	uint8_t counter=0;
 
    while(1)
    {
 
		if ((btn_last)&&(!(PINC & (1<<PINC5)))) {
			++direction;
			direction%=2; 
		}
		btn_last=(PINC & (1<<PINC5));
 
		if (counter++ > 10) {
 
			counter=0;
 
			if (direction==UP)
				++active;
			else 
				--active;
 
			switch(active) {
				case 2:
					PORTD &= ~(1 << PIND6);
					PORTD |= (1 << PIND7);
					PORTB &= ~(1 << PINB0);
					break;
				case 3: 
					PORTD |= (1 << PIND6);
					PORTD &= ~(1 << PIND7);
					PORTB &= ~(1 << PINB0);
					break;
				default: 
					PORTD &= ~(1 << PIND6);
					PORTD &= ~(1 << PIND7);
					PORTB |= (1 << PINB0);
					active=(direction==UP)?1:4;
			}
		}
 
		_delay_ms(50);
    }
}

Test rotačních enkodérů

 PIN A:  __--__--__--__--    // weight 1
 PIN B:  ___--__--__--__--   // weight 2
 values: 00132013201320132
#define sbi(x, i) x |= (1 << i)
#define cbi(x, i) x &= ~(1 << i)
#define gbi(x, i) (!(x & (1 << i)))
#define ROT1_A_PORT     PORTC
#define ROT1_A_DDR      DDRC
#define ROT1_A_PIN      PINC
#define ROT1_A_P        PC3
#define ROT1_B_PORT     PORTC
#define ROT1_B_DDR      DDRC
#define ROT1_B_PIN      PINC
#define ROT1_B_P        PC4
/* Init Rotary Encoder */
cbi(ROT1_A_DDR, ROT1_A_P);
cbi(ROT1_B_DDR, ROT1_B_P);
cbi(ROT1_BTN_DDR, ROT1_BTN_P);

Algoritmus 1

uint8_t inline readRotary(void) {
  uint8_t rotval_now;
 
  rotval_now =  gbi(ROT1_A_PIN, ROT1_A_P);
  rotval_now += gbi(ROT1_B_PIN, ROT1_B_P)*2;
 
  if ((rotval_last==0)&&(rotval_now==1)) {
    rotval_last=rotval_now;
    return RIGHT;
  }
 
  if ((rotval_last==0)&&(rotval_now==2)) {
    rotval_last=rotval_now;
    return LEFT;
  }
 
  rotval_last=rotval_now;
  return NOCHNG;
}

Algoritmus 2

#define ROTA gbi(ROT1_A_PIN, ROT1_A_P)
#define ROTB gbi(ROT1_B_PIN, ROT1_B_P)

Varianta A

uint8_t inline readRotary2(void) {
 
  if(ROTA & (!ROTB)){
    loop_until_bit_is_set(ROT1_A_PIN, ROT1_A_P);
    if (ROTB) return RIGHT;
  }
 
  if(ROTB & (!ROTA)){
    loop_until_bit_is_set(ROT1_B_PIN, ROT1_B_P);
    if (ROTA) return LEFT;
  }
 
  if (ROTA & ROTB){
    loop_until_bit_is_set(ROT1_A_PIN, ROT1_A_P);
    return (ROTB)?RIGHT:LEFT;
  }
 
  return NOCHNG;
}

Varianta B

uint8_t inline readRotary3(void) {
 
  if(ROTA & (!rotval_last)) rotval_last=1;
  if (ROTB & ROTA & (rotval_last)) {
    rotval_last=2;
    return LEFT;
  }
 
  if(ROTA & (!ROTB) & rotval_last) {
    rotval_last=2;    
    return RIGHT;
  }
 
  if ((!ROTA)&!(ROTB)&(rotval_last==2)) rotval_last=0;
 
  return NOCHNG;
}

Algoritmus 3

uint8_t inline readRotary5(void) {
 
  static uint8_t waitcount = 0;
 
  if ( gbi(ROT1_B_PIN, ROT1_B_P) ) { 	//we have a trigger signal
 
    if ( !gbi(ROT1_A_PIN, ROT1_A_P) ) {  // rotating left or right?
      if ( rotval_last != RIGHT ) 	//debounce for polling
	      waitcount++;
      rotval_last = RIGHT;
    }
    else {
      if ( rotval_last != LEFT )		//debounce for polling
	      waitcount++;
      rotval_last = LEFT;
    }
 
  }
  else {
    rotval_last = NOCHNG;
    waitcount = 0;
  }
 
  if ( waitcount > 1 ) {  //only give a L/R value after non-wait transition
    waitcount = 0;
    return rotval_last;
  }
 
  return NOCHNG;	  //ignore
 
}

USB HID

Test V-USB

Teorie

Zprovoznění demo HID mouse

Předělání HID mouse na gamepad s rotačním enkodérem

TODO

log min/max variable type start + inc alg notice
32k/32 int16_t -32k + 100 pak to přeteče a půjde od -32k
0/32k uint16_t 0 + 100 nejvyšší bit vždy nulový &7fff
-32k/0 int16_t -32k + 100 nejvyšší bit vždy jednička OR 0x8000
0/1023 uint16_t 0 + 10 nejvyšších 6bitů vždy nulových &3ff
-512/511 int16_t -512 + 10 když větší než 511, tak -512
0/64k uint16_t 0 + 100 pak přeteče a půjde od nula

Test ADC

Plány

Zdroje