Commit ac61bd30 authored by BuildTools's avatar BuildTools
Browse files

Fixed PWM

parent 9788a10e
Loading
Loading
Loading
Loading
+58 −77
Original line number Diff line number Diff line
/*
 * PWM-LF.c
 *
 * Created: 29.01.2017 23:43:39
 * Author : Petter
 */ 

#define F_CPU 3333333UL
#define F_CPU 20000000UL


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdbool.h>

#define LED1 0 // port B, connected to WO0
#define LED2 1 // port B, connected to WO1
#define LED3 4 // Port B
#define SW1 5 // Port A
#define SW2 6 // Port A
#define SW3 7 // Port A

/*
In the pin definitions below, we have defined the PORT as well.
Everything works the same way as before, except you have to change PORTx with the PORT definition. 
Example: LED1_PORT.OUTSET = (1 << LED1);
*/


#define LED1		4		//pin
#define LED2		5		//pin
#define LED3		5		//pin

#define LED1_PORT	PORTD	//port
#define LED2_PORT	PORTD	//port
#define LED3_PORT	PORTC	//port

bool SW1_pressed,SW2_pressed; //Keeping track of button status


#define SW1			2		//pin
#define SW2			1		//pin
#define SW3			2		//pin

#define SW1_PORT	PORTC	//port
#define SW2_PORT	PORTD	//port
#define SW3_PORT	PORTD	//port

#define TOP_PERIOD 0x55

/*
    In this exercise, you will use PWM to control the brightness of LEDs
    Once we have PWM set up, controlling the brightness is super easy!
*/

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. 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);
	
	//Pullups
	PORTA.PIN5CTRL |= (1 << PORT_PULLUPEN_bp);
	PORTA.PIN6CTRL |= (1 << PORT_PULLUPEN_bp);
	PORTA.PIN7CTRL |= (1 << PORT_PULLUPEN_bp);	
	
	/*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.
	sei();
	
	LED1_PORT.DIRSET = (1 << LED1); //Datasheet say that we should put pins to PWM as outputs.
	LED2_PORT.DIRSET = (1 << LED2); //Also, since we put signals out on them, this make sense.
	
	/**
	In dataheet: "http://ww1.microchip.com/downloads/en/DeviceDoc/40002016A.pdf", section 4.1, Multiplexed signals, we see that if we want to use TCA0 with PD4 and PD5,
	 we need to use portmux to change TCA to Port D. We find that the led is at port D, pin 4 and 5 by looking at datasheets and silk text for PCBs.
	*/
	PORTMUX.TCAROUTEA = (0x3 << 0); 
	
	//First, enable the timer
	TCA0.SINGLE.CTRLA |= (TCA_SINGLE_ENABLE_bm); 
	TCA0.SPLIT.CTRLD |= (1 << TCA_SPLIT_SPLITM_bp); //Set splitmode to get access to WO4 and WO5
	
	//Set the mode of the timer to single slope PWM
	TCA0.SINGLE.CTRLB |= (0x03 << TCA_SINGLE_WGMODE0_bp);
	TCA0.SPLIT.CTRLA |= (1 << TCA_SPLIT_ENABLE_bp) | (TCA_SPLIT_CLKSEL_DIV1_gc); //Enable the TCA and set prescaler to 1. Try different prescalers and see what happens.
	
	//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);
	TCA0.SPLIT.CTRLB |= (1 << TCA_SPLIT_HCMP1EN_bp) | (1 << TCA_SPLIT_HCMP2EN_bp); //Enable High Compare 1 and 2 to get output on WO4 and WO5. See Figure 19-13 in functional description datasheet.
	
	/*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.
	*/
	TCA0.SPLIT.HPER = TOP_PERIOD; // Set period for High compare. See figures in datasheet. But this is the PWM Period.

	//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)

	//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
	TCA0.SPLIT.HCMP1 = 0x00; //See figures in datasheet. This is the PWM duty cycle.
	TCA0.SPLIT.HCMP2 = 0x00;
	
	
    while(1){
@@ -75,36 +74,18 @@ int main(void)

		*/

		//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
				TCA0.SINGLE.CMP1 >>= 1;
				SW1_pressed = true;
		for (uint8_t i = 0; i < TOP_PERIOD; i++) {
			TCA0.SPLIT.HCMP1 = i;
			TCA0.SPLIT.HCMP2 = TOP_PERIOD-i;
			_delay_ms(2);
		}
		for (uint8_t i = TOP_PERIOD; i > 0;i--) {
			TCA0.SPLIT.HCMP1 = i;
			TCA0.SPLIT.HCMP2 = TOP_PERIOD-i;
			_delay_ms(2);
		}

		else{
			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
				TCA0.SINGLE.CMP0 >>= 1;
				SW2_pressed = true;
			}
		}
		
		else{
			SW2_pressed = false;
}

    }
}

Session2/PWM/.vs/PWM/v14/.atsuo

deleted100644 → 0
−27.5 KiB

File deleted.

Session2/PWM/PWM.atsln

deleted100644 → 0
+0 −22
Original line number Diff line number Diff line

Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "PWM", "PWM\PWM.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|AVR = Debug|AVR
		Release|AVR = Release|AVR
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR
		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR
		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal

Session2/PWM/PWM/Debug/Makefile

deleted100644 → 0
+0 −127
Original line number Diff line number Diff line
################################################################################
# Automatically-generated file. Do not edit!
################################################################################

SHELL := cmd.exe
RM := rm -rf

USER_OBJS :=

LIBS := 
PROJ := 

O_SRCS := 
C_SRCS := 
S_SRCS := 
S_UPPER_SRCS := 
OBJ_SRCS := 
ASM_SRCS := 
PREPROCESSING_SRCS := 
OBJS := 
OBJS_AS_ARGS := 
C_DEPS := 
C_DEPS_AS_ARGS := 
EXECUTABLES := 
OUTPUT_FILE_PATH :=
OUTPUT_FILE_PATH_AS_ARGS :=
AVR_APP_PATH :=$$$AVR_APP_PATH$$$
QUOTE := "
ADDITIONAL_DEPENDENCIES:=
OUTPUT_FILE_DEP:=
LIB_DEP:=
LINKER_SCRIPT_DEP:=

# Every subdirectory with source files must be described here
SUBDIRS := 


# Add inputs and outputs from these tool invocations to the build variables 
C_SRCS +=  \
../main.c


PREPROCESSING_SRCS += 


ASM_SRCS += 


OBJS +=  \
main.o

OBJS_AS_ARGS +=  \
main.o

C_DEPS +=  \
main.d

C_DEPS_AS_ARGS +=  \
main.d

OUTPUT_FILE_PATH +=PWM.elf

OUTPUT_FILE_PATH_AS_ARGS +=PWM.elf

ADDITIONAL_DEPENDENCIES:=

OUTPUT_FILE_DEP:= ./makedep.mk

LIB_DEP+= 

LINKER_SCRIPT_DEP+= 


# AVR32/GNU C Compiler
./main.o: .././main.c
	@echo Building file: $<
	@echo Invoking: AVR/GNU C Compiler : 5.4.0
	$(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE)  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega4809 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega4809" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"   -o "$@" "$<" 
	@echo Finished building: $<
	




# AVR32/GNU Preprocessing Assembler



# AVR32/GNU Assembler




ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif

# Add inputs and outputs from these tool invocations to the build variables 

# All Target
all: $(OUTPUT_FILE_PATH) $(ADDITIONAL_DEPENDENCIES)

$(OUTPUT_FILE_PATH): $(OBJS) $(USER_OBJS) $(OUTPUT_FILE_DEP) $(LIB_DEP) $(LINKER_SCRIPT_DEP)
	@echo Building target: $@
	@echo Invoking: AVR/GNU Linker : 5.4.0
	$(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe$(QUOTE) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -Wl,-Map="PWM.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega4809 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.2.209\gcc\dev\atmega4809"  
	@echo Finished building target: $@
	"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "PWM.elf" "PWM.hex"
	"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "PWM.elf" "PWM.eep" || exit 0
	"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "PWM.elf" > "PWM.lss"
	"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "PWM.elf" "PWM.srec"
	"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "PWM.elf"
	
	





# Other Targets
clean:
	-$(RM) $(OBJS_AS_ARGS) $(EXECUTABLES)  
	-$(RM) $(C_DEPS_AS_ARGS)   
	rm -rf "PWM.elf" "PWM.a" "PWM.hex" "PWM.lss" "PWM.eep" "PWM.map" "PWM.srec" "PWM.usersignatures"
	
 No newline at end of file

Session2/PWM/PWM/Debug/PWM.eep

deleted100644 → 0
+0 −1
Original line number Diff line number Diff line
:00000001FF
Loading