240 lines
10 KiB
Plaintext
240 lines
10 KiB
Plaintext
= Arduino Nano/ATMega328P =
|
|
|
|
A very small arduino product, better for hobby embedding
|
|
|
|
see [[arduino_techniques|Programming Techniques]]
|
|
|
|
See datasheet https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
|
|
|
|
== Features ==
|
|
|
|
* ATMEL AVR ATmega328P microcontroller
|
|
* 8 bit @16Mhz
|
|
* 2Kbytes SRAM
|
|
* 32Kbytes flash
|
|
* 1Kbytes EEPROM
|
|
* Three on board LED's * 20 IO pins
|
|
* 6 PWM and 6 ADC
|
|
|
|
== Notes ==
|
|
|
|
* WHEN UPLOADING BE SURE TO SET BOARD TO ATMEGA328OLD
|
|
- this is the atmega328old for BOARD_SUB in the makefile
|
|
|
|
=== Memory ===
|
|
|
|
* AVR instructions are 16 or 32bits wide, therefore the flash is 16K x 16
|
|
* EEPROM has endurance of ~10000 write cycles
|
|
* Program counter is 14 bits wide
|
|
* First 32 memory locations (0x0000 - 0x001F) are registers
|
|
* Next 64 registers are standard IO (0x0020 - 0x005F)
|
|
* Next 160 are extended IO (0x0060 - 0x00FF)
|
|
* Everything else is SRAM (0x0100 - 0x08FF)
|
|
|
|
=== IO ===
|
|
|
|
* GPIO pins
|
|
* Have a Data Direction Register (DDR)
|
|
- Sets if data should go in or out
|
|
* Is kept up via a [[multiplexer]] to decide which bit
|
|
|
|
=== Pins ===
|
|
|
|
The ATMega328P can control all of its pins via the use of an abstraction,
|
|
called ports. Each port has registers associated to it, and each pin
|
|
corresponds to a bit in a port register.
|
|
|
|
Port D controls pins D0 - 7,
|
|
Port C controls the analog Pins,
|
|
Port B controls pins D8 - 13
|
|
|
|
Each port has 3 registers associated with it. Port* is the register that allows
|
|
writing to the pins. These are PortB (0x25), PortC (0x28), and PortD (0x2B).
|
|
The Data Direction Registers (DDR*) determine if the Pin is used for Input or
|
|
Output. When a bit is set to zero (0), the pin will be used for input. Setting
|
|
a pin to one (1) will enable it for output. The three DDR* registers are DDRB,
|
|
(0x24), DDRC (0x27), and DDRD (0x2A). Finally, there are the PIN* registers,
|
|
which allow for input to taken. These registers are read only. The three PIN*
|
|
registers are PINB (0x23), PINC (0x26), and PIND (0x29).
|
|
|
|
To help with reading, the above info is in this table.
|
|
|
|
| Port | DDR | Port | Pin |
|
|
---------------------------
|
|
| B | 0x24 | 0x25 | 0x23 |
|
|
| C | 0x27 | 0x28 | 0x26 |
|
|
| D | 0x2A | 0x2B | 0x29 |
|
|
|
|
=== Interrupts ===
|
|
|
|
Interrupts are the same as OS typical interrupts, controlled by the Interrupt
|
|
lookup table. On this device the ILT is instead a control [[registers]]. The
|
|
code an interrupt calls is called an Interrupt Service Routine (ISR).
|
|
|
|
The External Interrupt Control Regsiter (EICR 0x69) is a register that allows you to set
|
|
the behaviour of the two built in interrupts. The Behaviour is set via setting
|
|
two bits. Bits 3-2 are for Interrupt 1 on pin D3, and Bits 1-0 are for
|
|
Interrupt 0 on pin D2. Below is a table of the values and their behaviour
|
|
|
|
| Bits | Description |
|
|
----------------------
|
|
| 00 | Low level makes an interrupt |
|
|
| 01 | Any logical change makes an interrupt |
|
|
| 10 | Falling edge makes an interrupt |
|
|
| 11 | Rising edge makes an interrupt |
|
|
|
|
To enable the interrupt, you must write a one (1) to the appropriate bit in the
|
|
External Interrupt Mask Register (EIMSK 0x3D). Bit 0 set INT0, and Bit 1 sets
|
|
INT1.
|
|
|
|
NOTE external activity on the pin, once the EIMSK bit is set, will cause an
|
|
interrupt even if the pin is set as an output pin.
|
|
|
|
Once an interrupt is triggered, the External Interrupt Flag Register (EIFR
|
|
0x3C) will have a one (1) written to the corresponding bit for that interrupt.
|
|
The flag is set automatically, and cleared once the interrupt has concluded.
|
|
The flag can be cleared by writing to it manually. Bit0 controlls INT0 and Bit
|
|
1 controlls INT1.
|
|
|
|
Finally, for interrupts to be enabled at all, a one (1) must be written to the
|
|
Status Register (SREG 0x5F). Bit 7 is the global interrupt enable flag, and
|
|
must have a one (1) written to it in order for interrupts to occour, regardless
|
|
of the state of the EIMSK register.
|
|
|
|
To implement an interrupt in code, see the following C example
|
|
{{{
|
|
//enable the interrupts as explained above
|
|
ISR(INT0_vect){
|
|
//perform interrupt task
|
|
}
|
|
}}}
|
|
|
|
=== Clock ===
|
|
|
|
The ATMega328P has 3 timers, two 8bit timers and one 16bit timer. These timers
|
|
can be used for PWM for motors and the like.
|
|
|
|
The timers are controlled by the General Timer/Counter Control Register (GTCCR
|
|
0x43). Bit 7 is the Timer/Counter sync Mode (TSM) and when set, halts the
|
|
timers so that they do not increment during configuration. Once TSM has a zero
|
|
wirtten to it, the PSRASY and PSRSYNC bits (bits 1-0 in this register) are
|
|
cleared via hardware, and the timers start counting. Bit 0 is the Prescaler
|
|
reset, and will reset the Timer/Counter 0 and 1 prescalers when 1 is written to
|
|
it. It is important to not that *Timer/Counter1 and 0 share the same prescaler
|
|
and a reset of the prescaler will affect both*
|
|
|
|
The Timer Counter 1 Control Register A (TCCR1A 0x80) is the register for
|
|
controlling Timer/Counter 1, along with Timer Counter 1 Control Register B
|
|
(TCCR1B 0x81). The high sets of two bits (bits 7-6 and 5-4), control the
|
|
compare output mode for channel A and B respectivly. These are controlled with
|
|
2 bit combinations as shown below.
|
|
|
|
NOTE These settings only apply to normal mode, and are on TTCR1A
|
|
|
|
| Bits | Description |
|
|
----------------------
|
|
| 00 | Normal Port operation, Comp register disconnected |
|
|
| 01 | Toggle OC1A/OC1B on compare match |
|
|
| 10 | Clear OC1A/OC1B on compare match (set output low) |
|
|
| 11 | Set OC1A/OC1B on compare match (set output high) |
|
|
|
|
TCCRB1B also can change the behaviour of the clock. Bit 7 sets the Input
|
|
Capture Noise Canceler (ICNC1). This will eliminate noise on the pin, and
|
|
delay the input caputre by 4 clock cycles. Bit 6 is the Input Capture Edge
|
|
Select 1 (ICES1). (To write about).
|
|
|
|
The lower 3 bits (2-0) determine the clock source. The possible vlaues are
|
|
shown below.
|
|
|
|
| Bits | Description |
|
|
----------------------
|
|
| 000 | No clock source (off) |
|
|
| 001 | CLK I/O / 1 (no prescale) |
|
|
| 010 | / 8 Prescaler |
|
|
| 011 | / 64 Prescaler |
|
|
| 100 | / 256 Prescaler |
|
|
| 101 | / 1024 Prescaler |
|
|
| 110 | External Clock source on T1 (falling edge) |
|
|
| 111 | External Clock source on T1 (rising edge) |
|
|
|
|
NOTE T1 will trigger the clock even if the pin in configured as output.
|
|
|
|
The mode of the timer is set using the lower two bits (1-0) of TCCR1A and bits
|
|
4-3 of TCCR1B. The two bits in TCCR1A are known as Waveform Generation Mode 11
|
|
(WGM11) and WGM10 for bits 1 and 0 respectivily. Bits 4-3 on TCCR1B are known
|
|
as WGM13 and WGM12 respecitvly. When ordred WGM13 through WGM10, they create a
|
|
4 bit value. The corresponding values and the effects are shown below.
|
|
|
|
| Mode | Mode of operation | TOP | Update OCR1* at | TOV1 Flag set on |
|
|
-----------------------------------------------------------------------
|
|
| 0 | Normal | 0xFFFF | Immediate | MAX |
|
|
| 1 | PWM, phase correct, 8bit | 0x00FF | TOP | BOTTOM |
|
|
| 2 | PWM, phase correct, 9-bit | 0x01FF | TOP | BOTTOM |
|
|
| 3 | PWM, phase correct, 10-bit | 0x03FF | TOP | BOTTOM |
|
|
| 4 | Clear on compare match | OCR1A | Immediate | MAX |
|
|
| 5 | Fast PWM, 8bit | 0x00FF | BOTTOM | TOP |
|
|
| 6 | Fast PWM, 9bit | 0x01FF | BOTTOM | TOP |
|
|
| 7 | Fast PWM, 10bit | 0x03FF | BOTTOM | TOP |
|
|
| 8 | PWM, phase and frequency correct | ICR1 | BOTTOM | BOTTOM |
|
|
| 9 | PWM, phase and frequency correct | OCR1A | BOTTOM | BOTTOM |
|
|
| 10 | PWM, phase correct | ICR1 | TOP | BOTTOM |
|
|
| 11 | PWM, phase correct | OCR1A | TOP | BOTTOM |
|
|
| 12 | CTC | ICR1 | Immediate | MAX |
|
|
| 13 | RESERVED | | | |
|
|
| 14 | Fast PWM | ICR1 | BOTTOM | TOP |
|
|
| 15 | Fast PWM | OCR1A | BOTTOM | TOP |
|
|
|
|
While in normal mode the Timer/Counter 1 Register counts up (inremental) and no
|
|
counter clear is done. The counter will overflow when the max 16 bit value
|
|
(0xFFFF) is reached. The registers that contain the counter values are The
|
|
Timer/Counter 1 Register (TCNT1H:TCNT1L 0x85[15:8] and 0x84[7:0], together TCNT1).
|
|
|
|
The Output Compare Register 1 A (OCR1AH:OCR1AL 0x89[15:8] and 0x88[0:7], together OCR1A)
|
|
and Output Compare Register 1 B (OCR1BH:OCR1BL 0x8B[15:8] and 0x8A[0:7], together OCR1B)
|
|
contain 16 bit values are contantly compared to the TCNT1 register. A compare operation is
|
|
performed, and a match generates an interupt.
|
|
|
|
These Interrupts can be turned on/off using the Timer/Counter 1 Interrupt Mask
|
|
Register (TIMSK1 0x6F). This register acts similary to the EIMSK register. Bit
|
|
5 enables Timer/Counter1 Input capture Interrupt (ICIE1), and the corresponsing
|
|
interrupt is triggerd when the ICF1 flag in TIFR1 is set.
|
|
Bits 2-0 enable the interrupts for Matches with Output Compare B, A, and
|
|
overflow resepectivly. When Bit 2 is set, the corresponding interrupt is
|
|
triggered only when the OCF1B flags in TIFR1 is set. This same principle
|
|
applies for OCF1A in TIFR1 for Bit 1, and TOV1 in TIFR1 for Bit 0. For more
|
|
info on TIFR1, refer below.
|
|
|
|
THe Timer/Counter 1 Interrupt Flag Register (TIFR1 0x36) is the register that holds
|
|
flags when Counter 1 (TCNT1) reaches the values in OCR1A and OCR1B. Bit 5 is
|
|
set when The input capture set by WGM to be used as the TOP value. Bits 2-0 are
|
|
set when TCNT1 matches the value in OCR1B, OCR1A, when when TCNT1 overflows,
|
|
respectivly.
|
|
|
|
==== Prescaler ====
|
|
|
|
To make the clock useful, the following will be an example of how to use Timer
|
|
1 to delay a certain amount of time. You will need the following information
|
|
|
|
* CPU freq (16MHz)
|
|
* Max timer value (0xFFFF or 65536)
|
|
* Chosen Prescaler (See above for prescaler values)
|
|
|
|
Divide the CPU freq by the chosen prescaler. Then divide that result through
|
|
the desired freqency. Be sure that the value is smaller than the max timer
|
|
value. If it is to large, choose a larger prescaler. Then place this in the
|
|
OCR** Register and enable the desired interrupt.
|
|
|
|
To assist in finding the correct value, below are the values of the clock speed
|
|
(16Mhz) over the prescalers.
|
|
|
|
NOTE to help with calculations, 0xFFFF is 65536 and 0xFF is 256
|
|
|
|
| prescaler | value |
|
|
---------------------
|
|
| 8 | 2000000 |
|
|
| 64 | 250000 |
|
|
| 256 | 62500 |
|
|
| 1024 | 15625 |
|
|
|
|
|