I have started to dive into MCU programming and have been working with some basic codes. I first did it with Arduino but now I'm trying with an ATTINY1616 MCU and I'm hardstuck in how to create a PWM effect that dims a LED on and off. I thought I had a working code but for some reason it will work with one and only one pin. I have read the datasheet and it confirms there there are more pins available for PWM and find no command or statement that I could be missing to use other pins.
The code will compile regardless of the pin that I select as output but in the MCU, PB0 is the only one that will work. Other pins won’t do anything, don’t give any output and the software (Microship Studio) doesn’t show any errors. I have even swapped the MCU for new ones.
I’m not very good at reading datasheets but I really don’t see any commands that specifically allow some pins to be PWM (https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny1614-16-17-DataSheet-DS40002204A.pdf, specifically section 20 of TCA). My theory is that since PB0 is shown as being WO0 for TCA0, this pin is like the default for the TCA function and I need a command to indicate that I want to use another but I can’t find anything that works.
#define F_CPU 20000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
void PWM_init() {
// Configure Timer/Counter 0 (TC0) for PWM generation
// Set TC0 waveform generation mode to Fast PWM
TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc | TCA_SINGLE_CMP0EN_bm;
// Set TC0 period (TOP value) to 8-bit resolution
TCA0.SINGLE.PER = 0xFF;
// Set TC0 PWM output on PB0 (LED pin)
PORTB.DIRSET = PIN0_bm;
//PORTA.DIRSET = PIN4_bm; <------Pin PA4. It won't work even if PB0 is removed
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm;
}
void PWM_control() {
// Define the number of steps and the delay between each step
const uint16_t numSteps = 256;
const uint16_t delayMs = 10;
// Fade in
for (uint16_t step = 0; step < numSteps; step++) {
// Set ADC value based on the step
uint16_t adcValue = step;
// Scale the ADC value to PWM range (0-255)
uint8_t pwmValue = adcValue >> 2; // Right shift by 2 (divide by 4)
// Update PWM duty cycle
TCA0.SINGLE.CMP0 = pwmValue;
// Delay between each step
_delay_ms(delayMs);
}
// Fade out
for (uint16_t step = 256; step > 0; step--) {
// Set ADC value based on the step
uint16_t adcValue = step;
// Scale the ADC value to PWM range (0-255)
uint8_t pwmValue = adcValue >> 2; // Right shift by 2 (divide by 4)
// Update PWM duty cycle
TCA0.SINGLE.CMP0 = pwmValue;
// Delay between each step
_delay_ms(delayMs);
}
}
int main() {
// Initialize PWM
PWM_init();
CPU_CCP = 0xD8; //enable write to protected register;
CLKCTRL_MCLKCTRLB = 0; // No prescaling to periphery, therefore 20MHz frequency;
while (1) {
// Control PWM
PWM_control();
_delay_ms(10);
}
return 0;
}
Have tried:
- Use Arduino version of the code on the MCU, it works.
- Simply change 'PORTx.DIRSET' to any other won't work, only in PB0
- A separate void function for another pin that didn't work
- Change some commands like 'TCA_SINGLE_CMP0EN_bm', 'TCA_SINGLE_WGMODE_SINGLESLOPE_gc', changed from TCA to TCB. Nothing has worked
E: Changes made for solution in PWM set up
TCA0.SPLIT.CTRLA = TCA_SINGLE_ENABLE_bp;
//SPLIT MODE INIT
TCA0.SPLIT.CTRLD = TCA_SINGLE_SPLITM_bm;
TCA0.SPLIT.HPER = 0xFF;
TCA0.SPLIT.CTRLA = TCA_SINGLE_ENABLE_bm;
TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP0EN_bm | TCA_SPLIT_HCMP1EN_bm | TCA_SPLIT_HCMP2EN_bm;
In the control, I just changed TCA0.SINGLE.CMP0 for TCA0.SPLIT.HCMP1 for pin PA4.