wip mod04 ex01
This commit is contained in:
@@ -1,43 +0,0 @@
|
|||||||
#include "header.h"
|
|
||||||
|
|
||||||
// 14.3.3 : alternate functions on port D
|
|
||||||
// PD2 : - INT0 (External Interrupt 0 Input)
|
|
||||||
// - PCINT18 (Pin Change Interrupt 18)
|
|
||||||
// 12.4 : Interrupt Vectors in ATmega328 and ATmega328P
|
|
||||||
// - INT0 : External Interrupt Request 0
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
DOWN,
|
|
||||||
UP
|
|
||||||
} State;
|
|
||||||
volatile uint8_t button_state = UP;
|
|
||||||
|
|
||||||
// Table 13-2 : interrupt types
|
|
||||||
#define INT0_LOW ((0 << ISC01) | (0 << ISC01))
|
|
||||||
#define INT0_LOGICAL ((0 << ISC01) | (1 << ISC01))
|
|
||||||
#define INT0_FALLING ((1 << ISC01) | (0 << ISC01))
|
|
||||||
#define INT0_RAISING ((1 << ISC01) | (1 << ISC01))
|
|
||||||
|
|
||||||
// use interruption to change led1 state when button1 is pressed
|
|
||||||
int main() {
|
|
||||||
MODE_OUTPUT(LED1);
|
|
||||||
CLEAR_ELEM(LED1);
|
|
||||||
MODE_INPUT(BUTTON1);
|
|
||||||
PULLUP_ON(BUTTON1);
|
|
||||||
|
|
||||||
SREG |= ENABLE_GLOBAL_INTERRUPT;
|
|
||||||
|
|
||||||
EIMSK = (1 << INT0); // 13.2.2 : Enable INT0 interrupt (EIMSK – External Interrupt Mask Register)
|
|
||||||
EICRA = INT0_LOGICAL; // Table 13-2 : trigger type (EICRA – External Interrupt Control Register A)
|
|
||||||
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR(INT0_vect) {
|
|
||||||
_delay_ms(50);
|
|
||||||
button_state = (button_state == UP) ? DOWN : UP;
|
|
||||||
if (button_state == UP) {
|
|
||||||
TOGGLE_ELEM(LED1);
|
|
||||||
}
|
|
||||||
// EIFR = (1 << INTF0); // 13.2.3 : clear flag, why ? i think it only indicates that a trigger event has occured
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "bitmanip.h"
|
#include "bitmanip.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// PROTOTYPES
|
// PROTOTYPES
|
||||||
58
module04/ex01/main.c
Normal file
58
module04/ex01/main.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
// 14.3.1 : alternate functions for led2 PB1
|
||||||
|
// - OC1A (Timer/Counter1 Output Compare Match A Output)
|
||||||
|
// - 16.11.1 controlled by COM1A1:0 in TCCR1A
|
||||||
|
// - Table 16-2 : Compare Output Mode, Fast PWM
|
||||||
|
// (1 << COM1A1) | (0 << COM1A0) -> non-inverting mode
|
||||||
|
// - Table 16-4 : set timer 1 in fast PWM mode, with top as ICR1 or OCR1A
|
||||||
|
// - ICR1 : Input Capture Register ((1 << WGM13) | (1 << WGM12) | (1 << WGM11) | (0 << WGM10))
|
||||||
|
// - OCR1A : Output Compare Register ((1 << WGM13) | (1 << WGM12) | (1 << WGM11) | (1 << WGM10))
|
||||||
|
// -> if OCR1A is top, it's also duty cycle, so changing duty cycle will also change frequency
|
||||||
|
// -> if ICR1 is top, OCR1A is duty cycle, so it can be changed independantly
|
||||||
|
// - PCINT1 (Pin Change Interrupt 1) : to interrupt when pin change, in input mode only
|
||||||
|
|
||||||
|
// calulations
|
||||||
|
// - frequency is 16Mhz -> it means that the clock runs 16 000 000 times per seconds
|
||||||
|
// - and the timer1 can store 16 bits value of cycle -> which is 2^16 = 65536
|
||||||
|
// - so it will only last 65536/16000000 = 0,004096 second
|
||||||
|
// - if i want my cycle to be 0.001 second, prescaler 1 is enough
|
||||||
|
// - if i want my cycle to be 0.01 second, which prescaler ?
|
||||||
|
// - 8 * 0,004096 = 0.032768 -> it is enough
|
||||||
|
// - 64 * 0,004096 = 0.262144 -> it is largely enough
|
||||||
|
// - if i choose prescaler 1 for a duration of 0.001 seconds, i need to restart the clock after how many cycles :
|
||||||
|
// - (16000000 / 1) * 0.001 = 16000 ticks -> set ICR1 = 16000
|
||||||
|
// - if i choose prescaler 8 for a duration of 0.01 seconds, i need to restart the clock after how many cycles :
|
||||||
|
// - (16000000 / 8) * 0.01 = 20000 ticks -> set ICR1 = 20000
|
||||||
|
// - if i choose prescaler 64 for a duration of 0.01 seconds, i need to restart the clock after how many cycles :
|
||||||
|
// - (16000000 / 64) * 0.01 = 2500 ticks -> set ICR1 = 2500
|
||||||
|
|
||||||
|
// 16.9.3 : timer1 fast PWM
|
||||||
|
|
||||||
|
#define LED1_PWM_PRESCALER 8 // can be 1, 8, 64, 256, 1024
|
||||||
|
#define DUTY_CYCLE_PERCENT 9
|
||||||
|
#define FRQUENCY_MS 1
|
||||||
|
|
||||||
|
// use timers interruptions to varie led1 intensity using duty cycle, from 0% to 100% to 0% in 1 second
|
||||||
|
// timer1 sets the led duty cycle, timer0 change the duty cycle percentage
|
||||||
|
int main() {
|
||||||
|
MODE_OUTPUT(LED1);
|
||||||
|
CLEAR_ELEM(LED1);
|
||||||
|
MODE_OUTPUT(LED2);
|
||||||
|
CLEAR_ELEM(LED2);
|
||||||
|
|
||||||
|
SREG |= ENABLE_GLOBAL_INTERRUPT;
|
||||||
|
|
||||||
|
TCCR1A = (1 << WGM11); // Table 16-4 : set fast PWM mode with TOP ICR1, so we can use OCR1A for duty cycle and keep ICR1 for frequency
|
||||||
|
TCCR1B = (1 << WGM13) | (1 << WGM12);
|
||||||
|
|
||||||
|
TCCR1A |= (1 << COM1A1); // Table 16-2 : set non-inverting mode to trigger OC1A on fast PWM
|
||||||
|
|
||||||
|
TCCR1B |= PRESCALE_SET(LED1_PWM_PRESCALER); // Table 16-5 : set the appropriate prescale values
|
||||||
|
|
||||||
|
ICR1 = TIME_MS(FRQUENCY_MS, LED1_PWM_PRESCALER); // top value for Xms
|
||||||
|
|
||||||
|
OCR1A = PERCENT(DUTY_CYCLE_PERCENT, ICR1); // duty cycle frequence
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user