Loading Session2-LF/PWM-LF.c +37 −7 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ int main(void) //Set LED pins as output 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.PIN1CTRL |= (1 << PORT_INVEN_bp); PORTB.PIN4CTRL |= (1 << PORT_INVEN_bp); Loading @@ -38,19 +38,48 @@ int main(void) PORTA.PIN6CTRL |= (1 << PORT_PULLUPEN_bp); PORTA.PIN7CTRL |= (1 << PORT_PULLUPEN_bp); //Set clock prescaler div256 TCA0.SINGLE.CTRLA |= (TCA_SINGLE_ENABLE_bm); //Enable timer TCA0.SINGLE.CTRLB |= (0x05 << TCA_SINGLE_WGMODE0_bp); //Set mode to single slope /*We will be using timer 1 in single (not split) mode. It is highly recommended that you read chapter 20.3.3.4 in the datasheet on timer compare channels. There you will find a sub-capter on the single-slope PWM we will be using. */ //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); TCA0.SINGLE.CTRLB |= (TCA_SINGLE_CMP0EN_bm) | (TCA_SINGLE_CMP1EN_bm); //Enable the compare channels //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.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){ /*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(!SW1_pressed){ TCA0.SINGLE.CMP0 = (((TCA0.SINGLE.CMP0 << 1) + 1) & (0x0fff)); //Shift in a 1, and cut off excess to 12 bit Loading @@ -63,6 +92,7 @@ int main(void) SW1_pressed = false; } if (!(PORTA_IN & (1 << SW2))){ if(!SW2_pressed){ TCA0.SINGLE.CMP1 = (((TCA0.SINGLE.CMP1 << 1) + 1) & (0x0fff)); //Shift in a 1, and cut off excess to 12 bit Loading Session2-LF/TIMER-LF.c +20 −8 Original line number Diff line number Diff line Loading @@ -12,8 +12,8 @@ #include <util/delay.h> #include <avr/interrupt.h> #define LED1 0 // port B, connected to WO0 #define LED2 1 // port B, connected to WO1 #define LED1 0 // port B #define LED2 1 // port B #define LED3 4 // Port B Loading @@ -24,14 +24,24 @@ int main(void) */ PORTB.DIR = (1 << LED1) | (1 << LED2); PORTB.OUTTGL = (1 << LED1); //Only to start with LEDs off PORTB.OUTTGL = (1 << LED1); //Starting with only 1 LED on //We will be using a timer overflow interupt with timer A //We set the prescaler to clk=clk/256 /*We will be using timer A that will trigger an overflow interupt. 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); //Next we Enable timer interupts on overflow //Next we Enable timer interupts on overflow on timer A TCA0.SINGLE.INTCTRL |= (TCA_SINGLE_OVF_bm); //Finally we have to set the max value of the timer, the top. Loading @@ -50,9 +60,11 @@ int main(void) } ISR(TCA0_OVF_vect){ //Do something with the led(s), like toggle. 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 +28 −8 Original line number Diff line number Diff line Loading @@ -12,42 +12,61 @@ #include <avr/interrupt.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){ //From chapter 24.3 in datasheet PORTB.OUTSET = (1 << PIN2_bp); PORTB.DIRSET = (1 << PIN2_bp); //Setting up TX pin as output USART0.BAUDH = (baud >> 8); //Shift register right by 8 bits USART0.BAUDL = baud; //Set baud rate PORTB.OUTSET = (1 << PIN2_bp); //Setting the TX pin high 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 USART0.CTRLB |= (1 << USART_RXEN_bp) | (1 << USART_TXEN_bp); //Enable RX and TX USART0.CTRLA |= (1 << USART_RXCIE_bp); //Enable interrupts on incomming data USART0.CTRLA |= (1 << USART_RXCIE_bp); //Enable interrupts on incoming data } // function to transmit 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))){ //wait for previous transmit to finish }; //Put our new data into se sending register USART0.TXDATAL = data; } int main(void) { //Initialize the UART with our function. //We will be using a baudrate of 9600 (defined as BAUD_9600 at the top of the file) uart_init(BAUD_9600); uart_init(BAUD_9600); //start uart with baudrate of 9600 sei(); //Important for anything here to work sei(); //Enable inerrupt, important for anything here to work while (1) { //Do nothing, interrupts handle everything //We don't really need to do anything here. //the ISR will handle receiving. } } Loading @@ -55,6 +74,7 @@ int main(void) //Interrupt service routine for the receiver. ISR(USART0_RXC_vect){ //Read out the received data to a variable uint8_t data = USART0_RXDATAL; //Do things with data: uart_transmit(data + 1); //Example: Shift all characters by one step A -> B, B -> C etc. Loading Session2/Timer/main.c +3 −3 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ int main(void) /*We will be using timer A that will trigger an overflow interupt. This is a 16 bit timer that can run in 2 modes -sigle mode as 1 16-bit timer -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 adresses the control A register for timer A 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. Loading Loading @@ -58,7 +58,7 @@ ISR(TCA0_OVF_vect){ //Do something with the led(s), like toggle. //Clear the interupt flag. //Clear the interrupt flag. //If we do not clear the flag, we will instantly jump back into the ISR again } No newline at end of file Session2/UART/.gitignoredeleted 100644 → 0 +0 −2 Original line number Diff line number Diff line UART/Debug .vs Loading
Session2-LF/PWM-LF.c +37 −7 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ int main(void) //Set LED pins as output 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.PIN1CTRL |= (1 << PORT_INVEN_bp); PORTB.PIN4CTRL |= (1 << PORT_INVEN_bp); Loading @@ -38,19 +38,48 @@ int main(void) PORTA.PIN6CTRL |= (1 << PORT_PULLUPEN_bp); PORTA.PIN7CTRL |= (1 << PORT_PULLUPEN_bp); //Set clock prescaler div256 TCA0.SINGLE.CTRLA |= (TCA_SINGLE_ENABLE_bm); //Enable timer TCA0.SINGLE.CTRLB |= (0x05 << TCA_SINGLE_WGMODE0_bp); //Set mode to single slope /*We will be using timer 1 in single (not split) mode. It is highly recommended that you read chapter 20.3.3.4 in the datasheet on timer compare channels. There you will find a sub-capter on the single-slope PWM we will be using. */ //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); TCA0.SINGLE.CTRLB |= (TCA_SINGLE_CMP0EN_bm) | (TCA_SINGLE_CMP1EN_bm); //Enable the compare channels //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.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){ /*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(!SW1_pressed){ TCA0.SINGLE.CMP0 = (((TCA0.SINGLE.CMP0 << 1) + 1) & (0x0fff)); //Shift in a 1, and cut off excess to 12 bit Loading @@ -63,6 +92,7 @@ int main(void) SW1_pressed = false; } if (!(PORTA_IN & (1 << SW2))){ if(!SW2_pressed){ TCA0.SINGLE.CMP1 = (((TCA0.SINGLE.CMP1 << 1) + 1) & (0x0fff)); //Shift in a 1, and cut off excess to 12 bit Loading
Session2-LF/TIMER-LF.c +20 −8 Original line number Diff line number Diff line Loading @@ -12,8 +12,8 @@ #include <util/delay.h> #include <avr/interrupt.h> #define LED1 0 // port B, connected to WO0 #define LED2 1 // port B, connected to WO1 #define LED1 0 // port B #define LED2 1 // port B #define LED3 4 // Port B Loading @@ -24,14 +24,24 @@ int main(void) */ PORTB.DIR = (1 << LED1) | (1 << LED2); PORTB.OUTTGL = (1 << LED1); //Only to start with LEDs off PORTB.OUTTGL = (1 << LED1); //Starting with only 1 LED on //We will be using a timer overflow interupt with timer A //We set the prescaler to clk=clk/256 /*We will be using timer A that will trigger an overflow interupt. 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); //Next we Enable timer interupts on overflow //Next we Enable timer interupts on overflow on timer A TCA0.SINGLE.INTCTRL |= (TCA_SINGLE_OVF_bm); //Finally we have to set the max value of the timer, the top. Loading @@ -50,9 +60,11 @@ int main(void) } ISR(TCA0_OVF_vect){ //Do something with the led(s), like toggle. 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 +28 −8 Original line number Diff line number Diff line Loading @@ -12,42 +12,61 @@ #include <avr/interrupt.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){ //From chapter 24.3 in datasheet PORTB.OUTSET = (1 << PIN2_bp); PORTB.DIRSET = (1 << PIN2_bp); //Setting up TX pin as output USART0.BAUDH = (baud >> 8); //Shift register right by 8 bits USART0.BAUDL = baud; //Set baud rate PORTB.OUTSET = (1 << PIN2_bp); //Setting the TX pin high 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 USART0.CTRLB |= (1 << USART_RXEN_bp) | (1 << USART_TXEN_bp); //Enable RX and TX USART0.CTRLA |= (1 << USART_RXCIE_bp); //Enable interrupts on incomming data USART0.CTRLA |= (1 << USART_RXCIE_bp); //Enable interrupts on incoming data } // function to transmit 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))){ //wait for previous transmit to finish }; //Put our new data into se sending register USART0.TXDATAL = data; } int main(void) { //Initialize the UART with our function. //We will be using a baudrate of 9600 (defined as BAUD_9600 at the top of the file) uart_init(BAUD_9600); uart_init(BAUD_9600); //start uart with baudrate of 9600 sei(); //Important for anything here to work sei(); //Enable inerrupt, important for anything here to work while (1) { //Do nothing, interrupts handle everything //We don't really need to do anything here. //the ISR will handle receiving. } } Loading @@ -55,6 +74,7 @@ int main(void) //Interrupt service routine for the receiver. ISR(USART0_RXC_vect){ //Read out the received data to a variable uint8_t data = USART0_RXDATAL; //Do things with data: uart_transmit(data + 1); //Example: Shift all characters by one step A -> B, B -> C etc. Loading
Session2/Timer/main.c +3 −3 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ int main(void) /*We will be using timer A that will trigger an overflow interupt. This is a 16 bit timer that can run in 2 modes -sigle mode as 1 16-bit timer -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 adresses the control A register for timer A 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. Loading Loading @@ -58,7 +58,7 @@ ISR(TCA0_OVF_vect){ //Do something with the led(s), like toggle. //Clear the interupt flag. //Clear the interrupt flag. //If we do not clear the flag, we will instantly jump back into the ISR again } No newline at end of file
Session2/UART/.gitignoredeleted 100644 → 0 +0 −2 Original line number Diff line number Diff line UART/Debug .vs