AtMega4808 - Wave Form generator

Go To Last Post
29 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello.

 

I'm using this AVR IoT WG board that AVR Freaks gave away to some users.

I'm only trying to setup the AtMega4808 using MPLAB X IDE (v5.10) to try to program it to try to generate an 5KHz wave form.

My OS is Debian 9.6 and I'm using this User Manual and this Datasheet and I'm also using AVR-Tool Chain Docs to anything else that I might need. The version of AVR-Tool Chain MPLAB X IDE is using is 5.4.0.

 

The code I have is the following but it's not generating the required wave form with 5KHz frequency. The code is commented.

 

I need help to see what is wrong/missing, etc! I hope I provided all the information needed.

 

/*
 * File:   LedBlink.c
 * Author: PsySc0rpi0n
 *
 * Created on 20 de Fevereiro de 2019, 21:35
 */
#define F_CPU 20000000L

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>

/*
 *
 */

int main(int argc, char** argv) {
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf

    // Main Clock Configuration
    // page 84
    CLKCTRL_MCLKCTRLA &= ~CLKCTRL_CLKSEL_OSC20M_gc; // Select 20MHz Internal Oscillator
    CLKCTRL_MCLKCTRLA |= CLKCTRL_CLKOUT_bp;         // Output the clock to CLKOUT pin
    // page 85
    CLKCTRL_MCLKCTRLB &= ~CLKCTRL_PEN_bp;           // Disable Prescaler

    // page
    TCA0_SINGLE_CMP0 = 0x07cf;                                     // TOP --> 5000Hz = (20e6)/(2*1(CMPn + 1)) <=> CMPn = 1999

    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf, page 190, 208,
    TCA0_SINGLE_CTRLB |= (1 << 0);                                 // Wave Generation Mode --> FRQ
    TCA0_SINGLE_EVCTRL &= ~( (1 << 2) | (1 << 1) | (1 << 0));      //Incremental Ticks counting mode (Positive edge) - No events counting
    TCA0_SINGLE_CTRLB |= (1 << 4);                                 //Compare channels enabled

    for ( ; ;){

    }
    return (EXIT_SUCCESS);
}

 

This topic has a solution.
Last Edited: Mon. Feb 25, 2019 - 10:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) The clock registers are protected. See this tutorial for the correct way to set the clock speed: https://www.avrfreaks.net/forum/...

2) you are not setting any port as output, so you cannot see the wave. That is, you need to do step 4 as described in the datasheet, you did only steps 1-3:

 

20.3.3.4.1 Waveform Generation

 

The compare channels can be used for waveform generation on the corresponding port pins. To make the waveform visible on the connected port pin, the following requirements must be met:

1. A Waveform Generation mode must be selected by writing the WGMODE bit field in TCAn.CTRLB.

2. The TCA is counting clock ticks, not events (CNTEI=0 in TCAn.EVCTRL).

3. The compare channels used must be enabled (CMPnEN=1 in TCAn.CTRLB). This will override the corresponding port pin output register. An alternative pin can be selected by writing to the respective TCA Waveform Output n bit (TCA0n) in the Control C register of the Port Multiplexer (PORTMUX.CTRLC).

4. The direction for the associated port pin n must be configured as an output (PORTx.DIR[n]=1).

5. Optional: Enable inverted waveform output for the associated port pin n (INVEN=1 in PORTx.PINn).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

1) The clock registers are protected. See this tutorial for the correct way to set the clock speed: https://www.avrfreaks.net/forum/...

2) you are not setting any port as output, so you cannot see the wave. That is, you need to do step 4 as described in the datasheet, you did only steps 1-3:

 

20.3.3.4.1 Waveform Generation

 

The compare channels can be used for waveform generation on the corresponding port pins. To make the waveform visible on the connected port pin, the following requirements must be met:

1. A Waveform Generation mode must be selected by writing the WGMODE bit field in TCAn.CTRLB.

2. The TCA is counting clock ticks, not events (CNTEI=0 in TCAn.EVCTRL).

3. The compare channels used must be enabled (CMPnEN=1 in TCAn.CTRLB). This will override the corresponding port pin output register. An alternative pin can be selected by writing to the respective TCA Waveform Output n bit (TCA0n) in the Control C register of the Port Multiplexer (PORTMUX.CTRLC).

4. The direction for the associated port pin n must be configured as an output (PORTx.DIR[n]=1).

5. Optional: Enable inverted waveform output for the associated port pin n (INVEN=1 in PORTx.PINn).

 

I thought that was being accomplished by the following line:

CLKCTRL.MCLKCTRLA |= (1 << CLKCTRL_CLKOUT_bp);   // Set CLKOUT pin as output

But as it is not, I'm removing it!

 

 

Also, in step 3 I cannot find any register CTRLC in PORTMUX... Can you check that, please?

 

And I do not understand Step 4.

"The direction for the associated port pin n..." <-- What associated port? What pin?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

Also, in step 3 I cannot find any register CTRLC in PORTMUX... Can you check that, please?

 

Datasheet error. There are lots of them, due to hasty copy/paste from similar devices by the people who write the datasheets. The correct register here is PORTMUX.TCAROUTEA. In this register you can select the pin where you want the wave to appear.

 

PsySc0rpi0n wrote:

And I do not understand Step 4.

"The direction for the associated port pin n..." <-- What associated port? What pin?

 

Ok, so let's say you selected PORTA as TCA0 output on the PORTMUX.TCAROUTEA register (the default). Now you need to enable the output of CMP0, which is the one you are using.

The mega4809 has 2 manuals, the "MegaAVR 0 Series Manual", and the "ATmega3209/4809 – 48-pin Data Sheet" which has specific characteristics of these models, including the pinout, which is what you need.

 

Go to chapter 4, "I/O Multiplexing and Considerations" and look for the CMP0 output of TCA0. It's marked "0-WO0" and located on port A0.

So now, you need to set port A0 as output. To learn how to do it, read chapter 15 of the Manual, called "I/O Pin Configuration (PORT)".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, this is what I tried but still can't see the waveform in PA0.

 

/* 
 * File:   LedBlink.c
 * Author: PsySc0rpi0n
 *
 * Created on 20 de Fevereiro de 2019, 21:35
 */
#define F_CPU 20000000UL

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>

/*
 * 
 */

int main(int argc, char** argv) { 
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf
    
    // Main Clock Configuration
    // page 84
    CLKCTRL_MCLKCTRLA &= ~CLKCTRL_CLKSEL_OSC20M_gc; // Select 20MHz Internal Oscillator
    // page 85
    CLKCTRL_MCLKCTRLB &= ~CLKCTRL_PEN_bp;           // Disable Prescaler
    
    
    // page 
    TCA0_SINGLE_CMP0 = 0x07cf;                                     // TOP --> 5000Hz = (20e6/6)/(2*1(CMPn + 1)) <=> CMPn = 1999
    
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf, page 190, 208, 
    TCA0_SINGLE_CTRLB |= (1 << 0);                                 // Wave Generation Mode --> FRQ
    TCA0_SINGLE_EVCTRL &= ~( (1 << 2) | (1 << 1) | (1 << 0));      // Incremental Ticks counting mode (Positive edge) - No events counting
    TCA0_SINGLE_CTRLB |= TCA_SINGLE_CMP0EN_bp;                     // Compare channels enabled
    PORTMUX.TCAROUTEA &= ~PORTMUX_TCA0_gm;                         // Set PA[0:5] as output for the wave form
    PORTA_OUT |= (1 << PIN0_bp);                                   // Set PIN0 of PORTA as output to see waveform
    for ( ; ;){

    }
    return (EXIT_SUCCESS);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just noticed the compilation output says this:

make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory '/media/wdelements/Microchip/MPLAB-X/Projects/LedBlink.X'
make  -f nbproject/Makefile-default.mk dist/default/production/LedBlink.X.production.hex
make[2]: Entering directory '/media/wdelements/Microchip/MPLAB-X/Projects/LedBlink.X'
"/home/narayan/avr8-gnu-toolchain-linux_x86_64/bin/avr-gcc"   -mmcu=atmega4808  -I "/opt/microchip/mplabx/v5.10/packs/Atmel/ATmega_DFP/1.2.285/include"  -B "/opt/microchip/mplabx/v5.10/packs/Atmel/ATmega_DFP/1.2.285/gcc/dev/atmega4808"  -x c -c -D__ATmega4808__  -funsigned-char -funsigned-bitfields -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -Wall -MD -MP -MF "build/default/production/LedBlink.o.d" -MT "build/default/production/LedBlink.o.d" -MT build/default/production/LedBlink.o  -o build/default/production/LedBlink.o LedBlink.c  -DXPRJ_default=default   
"/home/narayan/avr8-gnu-toolchain-linux_x86_64/bin/avr-gcc"  -mmcu=atmega4808  -B "/opt/microchip/mplabx/v5.10/packs/Atmel/ATmega_DFP/1.2.285/gcc/dev/atmega4808"  -D__ATmega4808__  -Wl,-Map="dist/default/production/LedBlink.X.production.map"    -o dist/default/production/LedBlink.X.production.elf build/default/production/LedBlink.o      -DXPRJ_default=default    -Wl,--defsym=__MPLAB_BUILD=1 -Wl,--gc-sections -Wl,--start-group  -Wl,-lm -Wl,--end-group 
"/home/narayan/avr8-gnu-toolchain-linux_x86_64/bin"/avr-objcopy -O ihex "dist/default/production/LedBlink.X.production.elf" "dist/default/production/LedBlink.X.production.hex"
make[2]: Leaving directory '/media/wdelements/Microchip/MPLAB-X/Projects/LedBlink.X'
make[1]: Leaving directory '/media/wdelements/Microchip/MPLAB-X/Projects/LedBlink.X'

BUILD SUCCESSFUL (total time: 104ms)
Loading code from /media/wdelements/Microchip/MPLAB-X/Projects/LedBlink.X/dist/default/production/LedBlink.X.production.hex...
Configuration Bits: address 0x821282: FREQSEL = 0 does not match any valid value in the device database.
Setting to the default value.
Configuration Bits: address 0x83128A: LB = 0 does not match any valid value in the device database.
Setting to the default value.
Loading completed

Configuration Bits: address 0x821282: FREQSEL = 0 does not match any valid value in the device database. 

Configuration Bits: address 0x83128A: LB = 0 does not match any valid value in the device database.

 

Is this a problem?

Last Edited: Sat. Feb 23, 2019 - 06:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I decided to write a tutorial on timer A. It's for split mode, but it should help you: https://www.avrfreaks.net/forum/...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

I decided to write a tutorial on timer A. It's for split mode, but it should help you: https://www.avrfreaks.net/forum/...

 

Nice that you wrote that tutorial but for my case, I need to see what is wrong with my settings. This should be quite simple and I'm not being able to make it work.

 

I would appreciate that you could help me finding out what is wrong with my code or what setting am I missing...

 

Thank you

Psy

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

See these lines?

 

    TCA0_SINGLE_CTRLB |= TCA_SINGLE_CMP0EN_bp;                     // Compare channels enabled

    PORTA_OUT |= (1 << PIN0_bp);                                   // Set PIN0 of PORTA as output to see waveform

 

In one, you are using xxxxx_bp correctly, in the other you are not and should be using xxxxx_bm instead.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

See these lines?

 

    TCA0_SINGLE_CTRLB |= TCA_SINGLE_CMP0EN_bp;                     // Compare channels enabled

    PORTA_OUT |= (1 << PIN0_bp);                                   // Set PIN0 of PORTA as output to see waveform

 

In one, you are using xxxxx_bp correctly, in the other you are not and should be using xxxxx_bm instead.

 

So the first one should be:

 

TCA0_SINGLE_CTRLB |= (1 << TCA_SINGLE_CMP0EN_bp);

or the 2nd line be:

 

PORTA_OUT |= PIN0_bm;

 

 

I knoe that PIN0_bm translates to 0x01, PIN0_bp translates to 1, but they are the same thing just represented in different ways, one in hex and the other in decimal.

I'm used to do things with the shift operations like REGISTER |= (1 << 0) and so on, so, I'm not actually understanding what is the problem!

Last Edited: Sun. Feb 24, 2019 - 08:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I translate this to the bare bits and shift operations, the macros in these 2 lines would be:

 

TCA0_SINGLE_CTRLB |= TCA_SINGLE_CMP0EN_bp;

knowing by the header file iom4808.h that

 

TCA0_SINGLE_CMP0EN_bp

translates to a simple 4, the above complete line would translate to:

TCA0_SINGLE_CTRLB = TCA0_SINGLE_CTRLB | 4;

So I don't see a problem here.

 

For the 2nd line:

PORTA_OUT |= (1 << PIN0_bp);

knowing from the header file ion4808.h that

PIN0_bp

translates to a simple 0 (zero), the above complete line would translate to:

 

PORTA_OUT = PORTA_OUT | (1 << 0);

This would be setting pin 0 of register PORTA_OUT to 1, or output. I don't see a problem here too!

 

What am I missing?

 

 

 

----------

And I tried to change things to this, but still no success yet. I can't see any waveform at pin PA0 of this AVR IoT WG board.

/* 
 * File:   LedBlink.c
 * Author: PsySc0rpi0n
 *
 * Created on 20 de Fevereiro de 2019, 21:35
 */
#define F_CPU 20000000UL

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>

/*
 * 
 */

int main(int argc, char** argv) { 
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf
    
    // Main Clock Configuration
    // page 84
    CLKCTRL_MCLKCTRLA = ~CLKCTRL_CLKSEL_OSC20M_gc; // Select 20MHz Internal Oscillator
    // page 85
    CLKCTRL_MCLKCTRLB = ~CLKCTRL_PEN_bp;           // Disable Prescaler
    
    
    // page 
    TCA0_SINGLE_CMP0 = 0x07cf;                                     // TOP --> 5000Hz = (20e6/6)/(2*1(CMPn + 1)) <=> CMPn = 1999
    
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf, page 190, 208, 
    TCA0_SINGLE_CTRLB |= (1 << 0);                                 // Wave Generation Mode --> FRQ
    TCA0_SINGLE_EVCTRL &= ~( (1 << 2) | (1 << 1) | (1 << 0));      // Incremental Ticks counting mode (Positive edge) - No events counting
    TCA0_SINGLE_CTRLB |= (1 << TCA_SINGLE_CMP0EN_bp);                      // Compare channels enabled
    PORTMUX_TCAROUTEA &= ~PORTMUX_TCA00_bm;                          // Set PA[0:5] as output for the wave form
    PORTA_OUT |= (1 << PIN0_bp);                                    // Set PIN0 of PORTA as output to see waveform
    
    for ( ; ;){

    }
    return (EXIT_SUCCESS);
}

 

Last Edited: Sun. Feb 24, 2019 - 08:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anything with _bp is a Bit Position which is a decimal

number between 0 and 7.  The same thing with _bm

is a Bit Mask equivalent to (1 << XYZ_bp).

 

Values which require multiple bits are called groups

so you have a Group Mask designated by _gm and

_gc Group Codes (?) which are the bits necessary to

set the group to the correct value.  Before setting a

group code, use the group mask to clear all the bits

to zero.  There's also _gp for Group Position.

 

--Mike

 

EDIT: added _gc and _gp

 

Last Edited: Sun. Feb 24, 2019 - 09:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-mike wrote:

Anything with _bp is a Bit Position which is a decimal

number between 0 and 7.  The same thing with _bm

is a Bit Mask equivalent to (1 << XYZ_bp).

 

Values which require multiple bits are called groups

so you have a Group Mask designated by _gm and

_gc Group Codes (?) which are the bits necessary to

set the group to the correct value.  Before setting a

group code, use the group mask to clear all the bits

to zero.  There's also _gp for Group Position.

 

--Mike

 

EDIT: added _gc and _gp

 

 

I know about that and it's probably that that is generating confusion to me.

 

I even tried to remove all those MACROS and use the notation I'm more used to but still no good:

 

/* 
 * File:   LedBlink.c
 * Author: PsySc0rpi0n
 *
 * Created on 20 de Fevereiro de 2019, 21:35
 */
#define F_CPU 20000000UL

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>

/*
 * 
 */

int main(int argc, char** argv) { 
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf
    
    // Main Clock Configuration
    // page 84
    //CLKCTRL_MCLKCTRLA |= CLKCTRL_CLKSEL_OSC20M_gc;                  // Select 20MHz Internal Oscillator
    CLKCTRL_MCLKCTRLA &= ~((1 << 0x01) | (1 << 0x00));
    
    // page 85
    //CLKCTRL_MCLKCTRLB &= ~(1 << CLKCTRL_PEN_bp);                    // Disable Prescaler
    CLKCTRL_MCLKCTRLB &= ~(1 << 0x00);
    
    // page ??
    TCA0_SINGLE_CMP0 = 0x07cf;                                      // TOP --> 5000Hz = (20e6/6)/(2*1(CMPn + 1)) <=> CMPn = 1999
    
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf, page 190, 208, 
    TCA0_SINGLE_CTRLB |= (1 << 0);                                  // Wave Generation Mode --> FRQ
    TCA0_SINGLE_EVCTRL &= ~( (1 << 2) | (1 << 1) | (1 << 0));       // Incremental Ticks counting mode (Positive edge) - No events counting
    
    //TCA0_SINGLE_CTRLB |= (1 << TCA_SINGLE_CMP0EN_bp);               // Compare channels enabled
    TCA0_SINGLE_CTRLB |= (1 << 0x01);
    
    //PORTMUX_TCAROUTEA &= ~PORTMUX_TCA00_bm;                         // Set PA[0:5] as output for the wave form
    PORTMUX_TCAROUTEA &= ~((1 << 0x02) | (1 << 0x01) | (1 << 0x00));
    
    PORTA_OUT |= (1 << 0x00);                                    // Set PIN0 of PORTA as output to see waveform
    
    for ( ; ;){

    }
    return (EXIT_SUCCESS);
}

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another Freak here has compiled the application notes for this family, give them a try, they should help:

https://www.avrfreaks.net/forum/...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Finally I made it thanks to @El Tangas link above and Moe123 links.

 

Here is the code I used:

 

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>

/*
 * 
 */

void Clock_Init(void){
    // Main Clock Configuration
    
    CPU_CCP = CCP_IOREG_gc;
    // Select 20MHz Internal Oscillator
    CLKCTRL_MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc;
    
    CPU_CCP = CCP_IOREG_gc;
    // Disable Prescaler
    CLKCTRL_MCLKCTRLB = ~CLKCTRL_PEN_bm;
    
    while(CLKCTRL_MCLKSTATUS & CLKCTRL_SOSC_bm);
}
void Port_Init(void){
    PORTA_DIR |= PIN0_bm;
}
void TimerA_Init(void){
    // Set PA[0:5] as output for the wave form
    PORTMUX_TCAROUTEA =  PORTMUX_TCA0_PORTA_gc;
    
    //Frequency Mode and Compare Channels enabled
    TCA0_SINGLE_CTRLB = TCA_SINGLE_WGMODE_FRQ_gc | TCA_SINGLE_CMP0EN_bm;
    
    //Disable Event count. Ticks counter instead
    TCA0_SINGLE_CTRLA &= ~(TCA_SINGLE_CNTEI_bm);
    
    // TOP --> 5000Hz = (20e6/6)/(2*1(CMPn + 1)) <=> CMPn = 1999
    TCA0_SINGLE_CMP0 = 0x07cf;
    
    //Select DIV1 for Timer prescaler and Enable peripheral
    TCA0_SINGLE_CTRLA =  (TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm); 
}

int main(int argc, char** argv) { 
    //http://ww1.microchip.com/downloads/en/DeviceDoc/40002015A.pdf
    
    Clock_Init();
    Port_Init();
    TimerA_Init();
    
    for ( ; ;){

    }
    return (EXIT_SUCCESS);
}

 

 

This is what I get in the scope

Frequency Wave Form

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now I'm trying to check what was wrong in the previous code I had but I can't figure out something.

 

This:

TCA0_SINGLE_CTRLB = TCA_SINGLE_WGMODE_FRQ_gc | TCA_SINGLE_CMP0EN_bm;

is the same as:

 

TCA0_SINGLE_CTRLB = 0x11;

 

And I was trying another way of doing this but I can't figure out why these 2 lines

TCA0_SINGLE_CTRLB = ~( (1 << 0x02) | (1 << 0x01));
TCA0_SINGLE_CTRLB = ((1 << 0x10) | (1 << 0x00));

are not the same as the previous ones. Can anyone help me?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nevermind... Noob mistake!

 

It should be

TCA0_SINGLE_CTRLB &= ~( (1 << 0x02) | (1 << 0x01));
TCA0_SINGLE_CTRLB |= ((1 << 0x04) | (1 << 0x00));

instead.

Last Edited: Tue. Feb 26, 2019 - 07:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

TCA0_SINGLE_CTRLB &= ~( (1 << 0x02) | (1 << 0x01));
TCA0_SINGLE_CTRLB |= ((1 << 0x04) | (1 << 0x00));

Or do it all in one statement:

TCA0_SINGLE_CTRLB = (TCA0_SINGLE_CTRLB & ~((1 << 0x02) | (1 << 0x01)))
                                       |  ((1 << 0x04) | (1 << 0x00));

so TCA0_SINGLE_CTRLB is updated atomically.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-mike wrote:

PsySc0rpi0n wrote:

 

TCA0_SINGLE_CTRLB &= ~( (1 << 0x02) | (1 << 0x01));
TCA0_SINGLE_CTRLB |= ((1 << 0x04) | (1 << 0x00));

Or do it all in one statement:

TCA0_SINGLE_CTRLB = (TCA0_SINGLE_CTRLB & ~((1 << 0x02) | (1 << 0x01)))
                                       |  ((1 << 0x04) | (1 << 0x00));

so TCA0_SINGLE_CTRLB is updated atomically.

 

--Mike

 

 

Thanks.

I'll use that notation...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I have one more problem.

 

I tried to setup the chip to generate a Dual Slope pulse train, 50Hz, 30% Duty Cycle but I cna't make it to show up on any other pin other than Pin 0 of PORTA.

 

The code that is working for Pin 0 of PORTA is this:

#define F_CPU 20000000UL

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <inttypes.h>
/*
 * 
 */

void CPU_Clock_Init(void){
    // Enable Protected Registers Write
    CPU_CCP = CCP_IOREG_gc;
    // Set Main Clock Prescaler and enable it
    CLKCTRL_MCLKCTRLB = CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm;
    
    // Enable Protected Registers Write
    CPU_CCP = CCP_IOREG_gc;
    // Select 20MHz Internal Oscillator
    CLKCTRL_MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc;
    
    // Wait until clock setting is stable
    while (CLKCTRL_MCLKSTATUS & CLKCTRL_SOSC_bm);
}

void TCA0_DualSlope_Init(void){
    // Select PORT to show wave form
    PORTMUX_TCAROUTEA = PORTMUX_TCA0_PORTA_gc;
    //Select Wave form mode and Compare channel to be used [DSBOTTOM] and [CPM0]
    TCA0_SINGLE_CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_DSBOTTOM_gc;
    // Set counter to count cpu ticks instead of events
    TCA0_SINGLE_EVCTRL &= ~(TCA_SINGLE_CNTEI_bm);
    // Set signal period of 50Hz according to Timer Prescaler of 8x, 50Hz period and 20MHz/64 CPU Clock Frequency
    // Freq = Freq_CPU / (2 * TCA_Prescaler * TCA_Perdiod) <=> TCA_Period = Freq_CPU / (2 * TCA_Prescaler * Freq)
    TCA0_SINGLE_PERBUF = 0x0186; //hex 390 - 0x0186
    // Set  Duty cycle of 30%
    TCA0_SINGLE_CMP0BUF = 0x0082;
    // Set Timer A prescaler to 8 and enable peripheral
    TCA0_SINGLE_CTRLA = TCA_SINGLE_CLKSEL_DIV8_gc | TCA_SINGLE_ENABLE_bm;    
}

void Port_Init(void){
    PORTA_DIR |= PIN0_bm;
}

int main(int argc, char** argv) {

    CPU_Clock_Init();
    Port_Init();
    TCA0_DualSlope_Init();
    
    return (EXIT_SUCCESS);
}

 

Then I tried to change the output pin to PORTC Pin 3 by changing only the following lines of the above code:

 

PORTMUX_TCAROUTEA = PORTMUX_TCA0_PORTC_gc;
PORTC_DIR |= PIN3_bm;

and the scope shows a flat line at 0V

 

Then I tried to change only the Pin to Pin 5 of PORTA by changing the same lines to the following:

 

PORTMUX_TCAROUTEA = PORTMUX_TCA0_PORTA_gc;
PORTA_DIR |= PIN5_bm;

and scope also shows a flat line at 0V.

 

What else I need to change?

 

I followed the examples posted by Moe123 here.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The datasheet says that, on the mega4808, the output of TCA0 channel 0 (called 0-WO0 on the TCA0 column) is on pin 0 of each port: PA0, PC0, PD0 and PF0.

It's here, chapter 4: http://ww1.microchip.com/downloa...

 

Where did you get those other ports you are trying to use?

 

(BTW, don't try to use PF0, it's connected to the external crystal on the XPlained board, forcing a square wave into the crystal may damage it)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

The datasheet says that, on the mega4808, the output of TCA0 channel 0 (called 0-WO0 on the TCA0 column) is on pin 0 of each port: PA0, PC0, PD0 and PF0.

It's here, chapter 4: http://ww1.microchip.com/downloa...

 

Where did you get those other ports you are trying to use?

 

(BTW, don't try to use PF0, it's connected to the external crystal on the XPlained board, forcing a square wave into the crystal may damage it)

 

You mean in that table? Or that there is some text saying exactly that?

 

I mean, I thought I could choose any pin of any port because of this:

 

I thought we could choose any pin between 0 and 5 of each port. Usually what is inside those brackets is a range, meaning PA0, PA1, PA2, PA3, PA4 and PA5...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interpreting datasheets is something you learn with years of experience.

As you know, timer A can have up to 6 channels (3 in 16 bit mode, 6 in 8 bit mode). That picture you showed, means the 6 channels are in pin 0-5 of PORTA by default. That is, channel 0 is in PA0, channel 1 in PA1 and so on.

The table shows where the signals will be if you enable multiplexing. So, if you enable multiplexing of TCA0 on PORTC, the channels will be in PORTC 0-5.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

Interpreting datasheets is something you learn with years of experience.

As you know, timer A can have up to 6 channels (3 in 16 bit mode, 6 in 8 bit mode). That picture you showed, means the 6 channels are in pin 0-5 of PORTA by default. That is, channel 0 is in PA0, channel 1 in PA1 and so on.

The table shows where the signals will be if you enable multiplexing. So, if you enable multiplexing of TCA0 on PORTC, the channels will be in PORTC 0-5.

 

I'm not sure I understand because in post #21 you said that the datasheet says that signals can only be seen in pin 0 of each port and then in the post above you are saying that if I enable multiplexing of TCA in PORTC, channels will be in PORTC 0-5, meaning in pins 0 to 5 (at least this is what I understand), therefore it looks like contradictory. So, this is still not fully clear to me! Could you please clarify?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

in post #21 you said that the datasheet says that signals can only be seen in pin 0 of each port 

 

El Tangas wrote:

The datasheet says that, on the mega4808, the output of TCA0 channel 0 (called 0-WO0 on the TCA0 column) is on pin 0 of each port: PA0, PC0, PD0 and PF0.

 

As you can see, I said the signal of channel 0 can be seen on PIN0 of each port. There is no contradiction, timer A has other channels, that will be on other pins.

 

So for example, if you want to see a signal on PC2, you need to use channel 2, then multiplex to PORTC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

PsySc0rpi0n wrote:

 

in post #21 you said that the datasheet says that signals can only be seen in pin 0 of each port 

 

 

El Tangas wrote:

 

The datasheet says that, on the mega4808, the output of TCA0 channel 0 (called 0-WO0 on the TCA0 column) is on pin 0 of each port: PA0, PC0, PD0 and PF0.

 

As you can see, I said the signal of channel 0 can be seen on PIN0 of each port. There is no contradiction, timer A has other channels, that will be on other pins.

 

So for example, if you want to see a signal on PC2, you need to use channel 2, then multiplex to PORTC.

 

Ahh, you mean CMP0, CMP1 and CPM2 registers?

Last Edited: Wed. Feb 27, 2019 - 08:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
Ahh, you mean CMP0, CMP1 and CPM2 registers?

 

Yes, exactly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can I keep asking questions here about the same chip but for different subjects? I mean, I want to ask some questions about the ADC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's better to create a new topic. This one was basically about Timer A, the ADC is a completely different subject.