Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
avrkurs
avrkurs
Commits
0913809d
Commit
0913809d
authored
Mar 10, 2017
by
spookysys
Browse files
lf dag 2
parent
0cbb0c29
Changes
6
Hide whitespace changes
Inline
Side-by-side
Session2-LF/PWM-LF.c
View file @
0913809d
...
@@ -28,7 +28,7 @@ int main(void)
...
@@ -28,7 +28,7 @@ int main(void)
//Set LED pins as output
//Set LED pins as output
PORTB
.
DIRSET
=
(
1
<<
LED1
)
|
(
1
<<
LED2
)
|
(
1
<<
LED3
);
PORTB
.
DIRSET
=
(
1
<<
LED1
)
|
(
1
<<
LED2
)
|
(
1
<<
LED3
);
//Because the LEDs are active low, we invert the output
//Because the LEDs are active low, we invert the output
. This means high PWM value -> bright led
PORTB
.
PIN0CTRL
|=
(
1
<<
PORT_INVEN_bp
);
PORTB
.
PIN0CTRL
|=
(
1
<<
PORT_INVEN_bp
);
PORTB
.
PIN1CTRL
|=
(
1
<<
PORT_INVEN_bp
);
PORTB
.
PIN1CTRL
|=
(
1
<<
PORT_INVEN_bp
);
PORTB
.
PIN4CTRL
|=
(
1
<<
PORT_INVEN_bp
);
PORTB
.
PIN4CTRL
|=
(
1
<<
PORT_INVEN_bp
);
...
@@ -38,19 +38,48 @@ int main(void)
...
@@ -38,19 +38,48 @@ int main(void)
PORTA
.
PIN6CTRL
|=
(
1
<<
PORT_PULLUPEN_bp
);
PORTA
.
PIN6CTRL
|=
(
1
<<
PORT_PULLUPEN_bp
);
PORTA
.
PIN7CTRL
|=
(
1
<<
PORT_PULLUPEN_bp
);
PORTA
.
PIN7CTRL
|=
(
1
<<
PORT_PULLUPEN_bp
);
//Set clock prescaler div256
/*We will be using timer 1 in single (not split) mode.
TCA0
.
SINGLE
.
CTRLA
|=
(
TCA_SINGLE_ENABLE_bm
);
//Enable timer
It is highly recommended that you read chapter 20.3.3.4 in the datasheet
TCA0
.
SINGLE
.
CTRLB
|=
(
0x05
<<
TCA_SINGLE_WGMODE0_bp
);
//Set mode to single slope
on timer compare channels.
There you will find a sub-capter on the single-slope PWM we will be using.
*/
TCA0
.
SINGLE
.
CTRLB
|=
(
TCA_SINGLE_CMP0EN_bm
)
|
(
TCA_SINGLE_CMP1EN_bm
);
//Enable the compare channels
//First, enable the timer
TCA0
.
SINGLE
.
CTRLA
|=
(
TCA_SINGLE_ENABLE_bm
);
//Set the mode of the timer to single slope PWM
TCA0
.
SINGLE
.
CTRLB
|=
(
0x03
<<
TCA_SINGLE_WGMODE0_bp
);
//We have to override the normal pin opperation so the PWM is pushed directly to the pin
//Hint: WO0 and WO1 are connected to leds. We need to override them to get the PWM out.
TCA0
.
SINGLE
.
CTRLB
|=
(
TCA_SINGLE_CMP0EN_bm
)
|
(
TCA_SINGLE_CMP1EN_bm
);
/*Timer A is a 16 bit timer. This will give us a frequency of 25Hz, we can see it flicker.
By lowering the period, (PER) we get higher frequency at the cost of lower resolution.
*/
//Set the period to 12 bit. (This results in a frequency of ~400Hz.)
TCA0
.
SINGLE
.
PER
=
0x0fff
;
//We set our top to have a sufficiently high frequency (Top at 16 bit (0xffff) ~25Hz, 12 bit (0x0fff) ~400Hz)
TCA0
.
SINGLE
.
PER
=
0x0fff
;
//We set our top to have a sufficiently high frequency (Top at 16 bit (0xffff) ~25Hz, 12 bit (0x0fff) ~400Hz)
TCA0
.
SINGLE
.
CMP0
=
0x0000
;
TCA0
.
SINGLE
.
CMP1
=
0x0fff
;
//We can now control the PWM duty cycle by simply writing values to the CMP0 and CMP1 registers.
TCA0
.
SINGLE
.
CMP0
=
0x0000
;
//We have inverted the pin outputs so this is MIN
TCA0
.
SINGLE
.
CMP1
=
0x0fff
;
//We have inverted the pin outputs so this is MAX
while
(
1
){
while
(
1
){
/*Have some fun with the leds. Examples:
Have them fade between max and min
Have them fade in a pattern (Heartbeat?)
Change the brightness based on buttons
*/
//Here we use button pushes to shift the CMP register so we get brightness steps
//adding and subtracting works just as well
//It is largely up to the student to choose how the led brightness is changed.
if
(
!
(
PORTA
.
IN
&
(
1
<<
SW1
))){
if
(
!
(
PORTA
.
IN
&
(
1
<<
SW1
))){
if
(
!
SW1_pressed
){
if
(
!
SW1_pressed
){
TCA0
.
SINGLE
.
CMP0
=
(((
TCA0
.
SINGLE
.
CMP0
<<
1
)
+
1
)
&
(
0x0fff
));
//Shift in a 1, and cut off excess to 12 bit
TCA0
.
SINGLE
.
CMP0
=
(((
TCA0
.
SINGLE
.
CMP0
<<
1
)
+
1
)
&
(
0x0fff
));
//Shift in a 1, and cut off excess to 12 bit
...
@@ -63,6 +92,7 @@ int main(void)
...
@@ -63,6 +92,7 @@ int main(void)
SW1_pressed
=
false
;
SW1_pressed
=
false
;
}
}
if
(
!
(
PORTA_IN
&
(
1
<<
SW2
))){
if
(
!
(
PORTA_IN
&
(
1
<<
SW2
))){
if
(
!
SW2_pressed
){
if
(
!
SW2_pressed
){
TCA0
.
SINGLE
.
CMP1
=
(((
TCA0
.
SINGLE
.
CMP1
<<
1
)
+
1
)
&
(
0x0fff
));
//Shift in a 1, and cut off excess to 12 bit
TCA0
.
SINGLE
.
CMP1
=
(((
TCA0
.
SINGLE
.
CMP1
<<
1
)
+
1
)
&
(
0x0fff
));
//Shift in a 1, and cut off excess to 12 bit
...
...
Session2-LF/TIMER-LF.c
View file @
0913809d
...
@@ -12,8 +12,8 @@
...
@@ -12,8 +12,8 @@
#include <util/delay.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/interrupt.h>
#define LED1 0 // port B
, connected to WO0
#define LED1 0 // port B
#define LED2 1 // port B
, connected to WO1
#define LED2 1 // port B
#define LED3 4 // Port B
#define LED3 4 // Port B
...
@@ -24,14 +24,24 @@ int main(void)
...
@@ -24,14 +24,24 @@ int main(void)
*/
*/
PORTB
.
DIR
=
(
1
<<
LED1
)
|
(
1
<<
LED2
);
PORTB
.
DIR
=
(
1
<<
LED1
)
|
(
1
<<
LED2
);
PORTB
.
OUTTGL
=
(
1
<<
LED1
);
//
Only to s
tart with LED
s
o
ff
PORTB
.
OUTTGL
=
(
1
<<
LED1
);
//
S
tart
ing
with
only 1
LED o
n
//We will be using a timer overflow interupt with timer A
/*We will be using timer A that will trigger an overflow interupt.
//We set the prescaler to clk=clk/256
This is a 16 bit timer that can run in 2 modes
-single mode as 1 16-bit timer
-dual/split mode as 2 8-bit timers
We will be using single mode in this exercise.
Hint because the register names can be hard to understand:
TCA0.SINGLE.CTRLA addresses the control A register for timer A
First we set the prescaler to clk=clk/256 and enable the timer.
This is done by setting the right bits in the control A register.
*/
TCA0
.
SINGLE
.
CTRLA
|=
(
TCA_SINGLE_CLKSEL_DIV256_gc
)
|
(
TCA_SINGLE_ENABLE_bm
);
TCA0
.
SINGLE
.
CTRLA
|=
(
TCA_SINGLE_CLKSEL_DIV256_gc
)
|
(
TCA_SINGLE_ENABLE_bm
);
//Next we Enable timer interupts on overflow
//Next we Enable timer interupts on overflow
on timer A
TCA0
.
SINGLE
.
INTCTRL
|=
(
TCA_SINGLE_OVF_bm
);
TCA0
.
SINGLE
.
INTCTRL
|=
(
TCA_SINGLE_OVF_bm
);
//Finally we have to set the max value of the timer, the top.
//Finally we have to set the max value of the timer, the top.
...
@@ -50,9 +60,11 @@ int main(void)
...
@@ -50,9 +60,11 @@ int main(void)
}
}
ISR
(
TCA0_OVF_vect
){
ISR
(
TCA0_OVF_vect
){
//Do something with the led(s), like toggle.
PORTB
.
OUTTGL
=
(
1
<<
LED1
)
|
(
1
<<
LED2
);
PORTB
.
OUTTGL
=
(
1
<<
LED1
)
|
(
1
<<
LED2
);
TCA0
.
SINGLE
.
INTFLAGS
=
(
TCA_SINGLE_OVF_bm
);
//Clear the interupt flag
//Clear the interrupt flag.
//If we do not clear the flag, we will instantly jump back into the ISR again
TCA0
.
SINGLE
.
INTFLAGS
=
(
TCA_SINGLE_OVF_bm
);
}
}
\ No newline at end of file
Session2-LF/UART-LF.c
View file @
0913809d
...
@@ -12,42 +12,61 @@
...
@@ -12,42 +12,61 @@
#include <avr/interrupt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/delay.h>
/*
In this exercise we will set up and use UART communication.
The embedded debugger has a virtual com port that we will use to communicate with the computer.
*/
void
uart_init
(
unsigned
long
baud
){
void
uart_init
(
unsigned
long
baud
){
//From chapter 24.3 in datasheet
//From chapter 24.3 in datasheet
PORTB
.
OUTSET
=
(
1
<<
PIN2_bp
);
PORTB
.
DIRSET
=
(
1
<<
PIN2_bp
);
//Setting up TX pin as output
PORTB
.
DIRSET
=
(
1
<<
PIN2_bp
);
//Setting up TX pin as output
USART0
.
BAUDH
=
(
baud
>>
8
);
//Shift register right by 8 bits
PORTB
.
OUTSET
=
(
1
<<
PIN2_bp
);
//Setting the TX pin high
USART0
.
BAUDL
=
baud
;
//Set baud rate
USART0
.
BAUDH
=
(
baud
>>
8
);
//Shift register right by 8 bits to get the 8 high bits
USART0
.
BAUDL
=
baud
;
//Set baud rate without shifting to get the 8 low bits
//It turns out the compiler can handle this automatically, meaning this works just as well:
//USART0.BAUD = baud;
//USART.CTRLC CMODE bits default to async, 1 stop bit, 8 bit character size
//USART.CTRLC CMODE bits default to async, 1 stop bit, 8 bit character size
USART0
.
CTRLB
|=
(
1
<<
USART_RXEN_bp
)
|
(
1
<<
USART_TXEN_bp
);
//Enable RX and TX
USART0
.
CTRLB
|=
(
1
<<
USART_RXEN_bp
)
|
(
1
<<
USART_TXEN_bp
);
//Enable RX and TX
USART0
.
CTRLA
|=
(
1
<<
USART_RXCIE_bp
);
//Enable interrupts on incom
m
ing data
USART0
.
CTRLA
|=
(
1
<<
USART_RXCIE_bp
);
//Enable interrupts on incoming data
}
}
// function to transmit data
// function to transmit data
void
uart_transmit
(
unsigned
char
data
){
void
uart_transmit
(
unsigned
char
data
){
//In this function we will be send data.
//First we should check that there isn't already data being sent
// if there is, we should probably wait for it to finish first
while
(
!
(
USART0
.
STATUS
&
(
1
<<
USART_DREIF_bp
))){
while
(
!
(
USART0
.
STATUS
&
(
1
<<
USART_DREIF_bp
))){
//wait for previous transmit to finish
//wait for previous transmit to finish
};
};
//Put our new data into se sending register
USART0
.
TXDATAL
=
data
;
USART0
.
TXDATAL
=
data
;
}
}
int
main
(
void
)
int
main
(
void
)
{
{
//Initialize the UART with our function.
uart_init
(
BAUD_9600
);
//start uart with baudrate of 9600
//We will be using a baudrate of 9600 (defined as BAUD_9600 at the top of the file)
uart_init
(
BAUD_9600
);
sei
();
//
I
mportant for anything here to work
sei
();
//
Enable inerrupt, i
mportant for anything here to work
while
(
1
)
while
(
1
)
{
{
//Do nothing, interrupts handle everything
//We don't really need to do anything here.
//the ISR will handle receiving.
}
}
}
}
...
@@ -55,6 +74,7 @@ int main(void)
...
@@ -55,6 +74,7 @@ int main(void)
//Interrupt service routine for the receiver.
//Interrupt service routine for the receiver.
ISR
(
USART0_RXC_vect
){
ISR
(
USART0_RXC_vect
){
//Read out the received data to a variable
uint8_t
data
=
USART0_RXDATAL
;
uint8_t
data
=
USART0_RXDATAL
;
//Do things with data:
//Do things with data:
uart_transmit
(
data
+
1
);
//Example: Shift all characters by one step A -> B, B -> C etc.
uart_transmit
(
data
+
1
);
//Example: Shift all characters by one step A -> B, B -> C etc.
...
...
Session2/Timer/main.c
View file @
0913809d
...
@@ -22,12 +22,12 @@ int main(void)
...
@@ -22,12 +22,12 @@ int main(void)
/*We will be using timer A that will trigger an overflow interupt.
/*We will be using timer A that will trigger an overflow interupt.
This is a 16 bit timer that can run in 2 modes
This is a 16 bit timer that can run in 2 modes
-sigle mode as 1 16-bit timer
-si
n
gle mode as 1 16-bit timer
-dual/split mode as 2 8-bit timers
-dual/split mode as 2 8-bit timers
We will be using single mode in this exercise.
We will be using single mode in this exercise.
Hint because the register names can be hard to understand:
Hint because the register names can be hard to understand:
TCA0.SINGLE.CTRLA adresses the control A register for timer A
TCA0.SINGLE.CTRLA ad
d
resses the control A register for timer A
First we set the prescaler to clk=clk/256 and enable the timer.
First we set the prescaler to clk=clk/256 and enable the timer.
This is done by setting the right bits in the control A register.
This is done by setting the right bits in the control A register.
...
@@ -58,7 +58,7 @@ ISR(TCA0_OVF_vect){
...
@@ -58,7 +58,7 @@ ISR(TCA0_OVF_vect){
//Do something with the led(s), like toggle.
//Do something with the led(s), like toggle.
//Clear the interupt flag.
//Clear the inter
r
upt flag.
//If we do not clear the flag, we will instantly jump back into the ISR again
//If we do not clear the flag, we will instantly jump back into the ISR again
}
}
\ No newline at end of file
Session2/UART/.gitignore
deleted
100644 → 0
View file @
0cbb0c29
UART/Debug
.vs
Session2/UART/.vs/UART/v14/.atsuo
deleted
100644 → 0
View file @
0cbb0c29
File deleted
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment