SW-UART big bang help

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

 

I try to use SW UART Transmitter for displaying into the serial terminal. I am using ATTiny461A and a FTDI usb to Serial board from Deek-Robot kit. I connect the PB0 of the MCU to the RX on the board, 5V and Ground.  The rest (cts, dtr) not connected. Is it error on the hardware ?  Any other hardware alternative or correct board i shall use ?

 

I use the Atmel Studio Visualiser to check the Serial Port Com10, nothing is display on it. 

The code is a modified from Marcel Meyer-Garcia github here. I just amend the Timer code to suit ATTiny461A timer code and the Compare Match change to OCR0B, value change to 26.

 

#define F_CPU 16e6

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

// change these to use another pin
#define TX_PORT PORTB
#define TX_PIN  PINB0
#define TX_DDR  DDRB
#define TX_DDR_PIN DDB0

volatile uint16_t tx_shift_reg = 0;


void UART_tx(char character)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //if sending the previous character is not yet finished, return
   //transmission is finished when tx_shift_reg == 0
   if(local_tx_shift_reg){return;}
   //fill the TX shift register witch the character to be sent and the start & stop bits (start bit (1<<0) is already 0)
   local_tx_shift_reg = (character<<1) | (1<<9); //stop bit (1<<9)
   tx_shift_reg = local_tx_shift_reg;
   //start timer0 with a prescaler of 8
   TCCR0B |= (1<<CS00)|(1<<CS01) ;
   
}

void UART_tx_str(char* string){
    while( *string ){
        UART_tx( *string++ );
        //wait until transmission is finished
        while(tx_shift_reg);
    }
}

void UART_init(){
   //set TX pin as output
   TX_DDR |= (1<<TX_DDR_PIN);
   TX_PORT |= (1<<TX_PIN);
   //set timer0 to CTC mode
   // TCCR0A = TCW0 | ICEN0 | INCC0 | ICES0 | ACIC0 | - | - | CTC0
   //            0  |  0    |    0  |     0 |  0    | 0 | 0 |   1
   TCCR0A = (1<<WGM00);//for attint461A
   //enable output compare 0 B interrupt
   
   // TCCR0B = |- | -| - | TSM | PSR0 | CS02 | CS01 | CS00
   //          | 0|0 | 0 |  0  | 0    | 0    |  1   | 1    //64
   //if 16MHz divide by 64, timer will clock at 250K Hz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 250 K = 26
   
   
   TIMSK |= (1<<OCIE0B);
   //set compare value to 26 to achieve a 9600 baud rate (i.e. 104µs)
   //together with the 16MHz/64 = 250kHz timer0 clock
   //IF use internal 16MHz, use precaler of 16. 
   /*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
     to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
     increasing or decreasing the value by 1 or 2 */
   OCR0B = 26;
   //enable interrupts
   sei();
}

int main(void)
{
   UART_init();

   while(1)
   {
    UART_tx_str("Hello world!\n");
    _delay_ms(100);
   }

   return 0;
}

 

This topic has a solution.
Last Edited: Thu. Jul 22, 2021 - 09:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the USB-serial board has LEDs, does one flash when you try to transmit?

 

Have you opened a serial port that talks to the FTDI chip AND do you have the port baud rate set to the same that the MCU is generating? 

 

Is 

 

#define F_CPU 16e6

a valid statement and is your MCU REALLY running at 16MHz? I would use

 

#define F_CPU 16000000 UL

 

Jim

 

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Tue. Jul 20, 2021 - 07:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you connect RX and TX together on the serial board can you send a character from a terminal program and see it echo back? And if you disconnect them does the echo stop?

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

Are you using a good 16MHz Crystal??...do not start off with an inaccurate frequency, or you can severely regret wasting days of your time for nothing.

 

Before you hooked up the AVR at all, did you take your adapter module and tie TX to RX  ???

Then your terminal should rcv & show what you type on the terminal...If that does not work, forget about even trying the AVR.

 

What does your scope show coming out of the AVR?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

In Post#1, I don't see the ISR code.

Is the ISR in your program but not copied to the post?

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

Chuck99 wrote:

In Post#1, I don't see the ISR code.

Is the ISR in your program but not copied to the post?

+1

 

You have:

   TIMSK |= (1<<OCIE0B);

and

   //enable interrupts
   sei();

but apparently nothing "behind" this to catch the ISR()??

 

Surely the whole point 

void UART_tx(char character)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //if sending the previous character is not yet finished, return
   //transmission is finished when tx_shift_reg == 0
   if(local_tx_shift_reg){return;}
   //fill the TX shift register witch the character to be sent and the start & stop bits (start bit (1<<0) is already 0)
   local_tx_shift_reg = (character<<1) | (1<<9); //stop bit (1<<9)
   tx_shift_reg = local_tx_shift_reg;
   //start timer0 with a prescaler of 8
   TCCR0B |= (1<<CS00)|(1<<CS01) ;
   
}

is that the value to send is placed in tx_shift_reg and then the timer started and then, on each interrupt it will shift one bit out. If you don't have the interrupt handler this is not going to happen.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
//timer0 compare A match interrupt
ISR(TIMER0_COMPB_vect)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //output LSB of the TX shift register at the TX pin
   if( local_tx_shift_reg & 0x01 )
   {
      TX_PORT |= (1<<TX_PIN);
   }
   else
   {
      TX_PORT &=~ (1<<TX_PIN);
   }
   //shift the TX shift register one bit to the right
   local_tx_shift_reg >>= 1;
   tx_shift_reg = local_tx_shift_reg;
   //if the stop bit has been sent, the shift register will be 0
   //and the transmission is completed, so we can stop & reset timer0
   if(!local_tx_shift_reg)
   {
      TCCR0B = 0;
     // TCNT = 0;
   }
}

 

The ISR was there, I miss copied into the forum. 

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

avrcandies wrote:

Are you using a good 16MHz Crystal??...do not start off with an inaccurate frequency, or you can severely regret wasting days of your time for nothing.

 

Before you hooked up the AVR at all, did you take your adapter module and tie TX to RX  ???

Then your terminal should rcv & show what you type on the terminal...If that does not work, forget about even trying the AVR.

 

What does your scope show coming out of the AVR?

 

Initially I did not use Crystal, because I in am using PLL mode setting in the switch. Since this is confusing.

 

I change to 8MHz at the fuse setting, 62, D7, EE.  Then I try, it doesnt show anything on the scope of PB0. I change the 8MHz program to below.

 

My terminal program did reflect back what I type if I tied RX and TX together.

 

#define F_CPU 8000000UL

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

// change these to use another pin
#define TX_PORT PORTB
#define TX_PIN  PINB0
#define TX_DDR  DDRB
#define TX_DDR_PIN DDB0

volatile uint16_t tx_shift_reg = 0;


void UART_tx(char character)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //if sending the previous character is not yet finished, return
   //transmission is finished when tx_shift_reg == 0
   if(local_tx_shift_reg){return;}
   //fill the TX shift register witch the character to be sent and the start & stop bits (start bit (1<<0) is already 0)
   local_tx_shift_reg = (character<<1) | (1<<9); //stop bit (1<<9)
   tx_shift_reg = local_tx_shift_reg;
   //start timer0 with a prescaler of 8
   TCCR0B |= (1<<CS01) ;
   
}

void UART_tx_str(char* string){
    while( *string ){
        UART_tx( *string++ );
        //wait until transmission is finished
        while(tx_shift_reg);
    }
}

void UART_init(){
   //set TX pin as output
   TX_DDR |= (1<<TX_DDR_PIN);
   TX_PORT |= (1<<TX_PIN);
   //set timer0 to CTC mode
   // TCCR0A = TCW0 | ICEN0 | INCC0 | ICES0 | ACIC0 | - | - | CTC0
   //            0  |  0    |    0  |     0 |  0    | 0 | 0 |   1
   TCCR0A = (1<<WGM00);//for attint461A
   //enable output compare 0 B interrupt
   
   // TCCR0B = |- | -| - | TSM | PSR0 | CS02 | CS01 | CS00
   //          | 0|0 | 0 |  0  | 0    | 0    |  1   | 0    //8
   //if 16MHz divide by 64, timer will clock at 250K Hz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 250 K = 26
   
   //use internal 8MHz, timer will clock at 1MHz 
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 1M = 104
   
   
   TIMSK |= (1<<OCIE0B);
   //set compare value to 26 to achieve a 9600 baud rate (i.e. 104µs)
   //together with the 16MHz/64 = 250kHz timer0 clock
   //IF use internal 16MHz, use precaler of 16. 
   /*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
     to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
     increasing or decreasing the value by 1 or 2 */
   OCR0B = 104;
   //enable interrupts
   sei();
}

int main(void)
{
   UART_init();

   while(1)
   {
    UART_tx_str("Hello world!\n");
    _delay_ms(100);
   }

   return 0;
}

//timer0 compare A match interrupt
ISR(TIMER0_COMPB_vect)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //output LSB of the TX shift register at the TX pin
   if( local_tx_shift_reg & 0x01 )
   {
      TX_PORT |= (1<<TX_PIN);
   }
   else
   {
      TX_PORT &=~ (1<<TX_PIN);
   }
   //shift the TX shift register one bit to the right
   local_tx_shift_reg >>= 1;
   tx_shift_reg = local_tx_shift_reg;
   //if the stop bit has been sent, the shift register will be 0
   //and the transmission is completed, so we can stop & reset timer0
   if(!local_tx_shift_reg)
   {
      TCCR0B = 0;
     // TCNT = 0;
   }
}

 

 

 

 

 

 

 

 

 

 

 

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

Why would TX_DDR_PIN be something different to TX_PIN ?!? That opens the potential for making one pin "output" but then actually driving the data on another pin?!?

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

hamisu wrote:

#define TX_PORT     PORTB
#define TX_PIN      PINB0
#define TX_DDR      DDRB
#define TX_DDR_PIN  DDB0

clawson wrote:
Why would TX_DDR_PIN be something different to TX_PIN ?!? That opens the potential for making one pin "output" but then actually driving the data on another pin?!?

 

A misunderstanding that PINB0 is somehow different from DDB0, perhaps ... ?

 

EDIT

 

There was a thread about it recently: https://www.avrfreaks.net/forum/how-read-input-particular-bit-port

 

add PORTB0 and PB0 to the list ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Jul 20, 2021 - 10:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I saw the code miss the start bit. I added the code

 

  local_tx_shift_reg &=~(1<<0);//start bit

 

after the stop bit line. Anyhow, still nothing from the scope. 

 

How many PIN is require to connect to the Serial hardware module ?  So far, I only connect PB0 to RX. GND, 5V. 

 

 

 

 

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

hamisu wrote:
The code is a modified from Marcel Meyer-Garcia github here.

Have you tried the unmodified code first?

 

Always best to spend some time with the original to gain understanding before trying to hack it 

 

It also means you have a working version to compare against ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I have the continuous pulse out from the scope. The hardware module TX LED is continuous blinking. I think the Studio Serial Terminal have problem, doesnt display anything and was always reseting the Atmel Studio. I cant use putty, any other hyper serial terminal I can use for Window system ?

 

 

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

hamisu wrote:
Anyhow, still nothing from the scope. 
Just do this:

#define F_CPU 16e6

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

int main(void) {
    DDRB = (1 << 0);
    while (1) {
        PORTB ^= (1 << 0);
        _delay_ms(100);
    }
}

What do you see on the scope? If nothing then that would appear to be the core of the problem !

 

If something is seen then one would then need to question whether the flow of execution is making it as far as your ISR().

 

(this is where debuggers come into their own! The 461 has debugWire - you may want to explore what would be involved in making use of that!)

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

hamisu wrote:
I think the Studio Serial Terminal have problem

again, that's a place where having a known-good reference would help you

 

I have the continuous pulse out from the scope

Where, exactly?

 

Post a trace (if it's a digital scope, use it's trace capture facility - far better than a photo!)

 

hamisu wrote:
I cant use putty

Why not?

 

 any other hyper serial terminal I can use for Window system ?

Loads!

 

See: https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I use another Serial Terminal, I only see continuous ............ Look like the timing is wrong ?

 

 

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

hamisu wrote:
I only see continuous ............ Look like the timing is wrong ?

Indeed - see Tip #2 in my signature.  Also FAQ #3 in clawson's 

 

You said you've got a scope - so you should be able to see what the timing is.

 

Hint: continuously transmitting 'U' gives a nice signal for looking at on a 'scope ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

hamisu wrote:
I think the Studio Serial Terminal have problem

again, that's a place where having a known-good reference would help you

 

I have the continuous pulse out from the scope

Where, exactly?

 

Post a trace (if it's a digital scope, use it's trace capture facility - far better than a photo!)

 

hamisu wrote:
I cant use putty

Why not?

 

 any other hyper serial terminal I can use for Window system ?

Loads!

 

See: https://www.avrfreaks.net/commen...

 

 

 

 

Putty does not response on setup. Just hang there.

 

 

 

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

It's too soon to be looking at putty if your scope shows there aren't any pulses on the line - what were you expecting putty to show if there is NO activity on the wire.

 

You have to solve problems by taking it a small step at a time.

 

For my money that starts by "wiggling the wire" using software in the micro, then looking for wire wiggling activity on the scope. See #14. If something as fundamental as that won't work then UART won't work and putty definitely won't show anything.

 

(BTW if you want to do a project that involves using a UART why would you pick a chip that does not actually have a UART?!)

Last Edited: Tue. Jul 20, 2021 - 12:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
if you want to do a project that involves using a UART why would you pick a chip that does not actually have a UART?!

Absolutely!

 

And, as this thread demonstrates, it's not trivial - so is it really worth the effort ?

 

It's not like chips with UARTs are rare or expensive these days ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And, as this thread demonstrates, it's not trivial - so is it really worth the effort ?

It's not too bad if you take it step-by-step, almost like good exercise.  As a practical matter--a built in UART wins hands-down.

 

Why fool with the PLL and other clock messing around???---start with a simple xtal & one major issue is put to rest...you can get a fancy source or scheme later.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

Could this be a simple case of the clock/8 fuse setting causing the baud rate to not be what the OP expects it to be?  

hamisu wrote:
I use another Serial Terminal, I only see continuous ............ Look like the timing is wrong ?

So this would indicate that some thing is leaving the port pin, as suggested above, write a simple test program to send the letter "U" over and over again, this will produce a square wave signal you can easily measure the bit time of the data that is sent, to verify your baud rate beliefs. 

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

avrcandies wrote:
start with a simple xtal & one major issue is put to rest...you can get a fancy source or scheme later.

+1

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

#define F_CPU 16e6

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

int main(void) {
    DDRB = (1 << 0);
    while (1) {
        PORTB ^= (1 << 0);
        _delay_ms(100);
    }
}

 

Hi, this code is working perfectly with train of square pulse display on the scope.  

 

When I try the debug-wire, I am not very good at it. It seem the code is stuck at second while loop here.

 

void UART_tx_str(char* string){
    while( *string ){
        UART_tx( *string++ );
        //wait until transmission is finished
        while(tx_shift_reg);  //<=====  stuck here....
    }
}

 

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

When I try the debug-wire

Why do you need that?  Send out some chars & see if the proper bits are present and the timing is correct...that tells you if you are really sending, at least for getting it going.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

hamisu wrote:
When I try the debug-wire, I am not very good at it.

Like any skill, it does take some learning & practice.

 

That's why I recommend it's one of the things you should learn right from the beginning: https://www.avrfreaks.net/commen...

 

Quote:
It seem the code is stuck at second while loop here.

void UART_tx_str(char* string){
    while( *string ){
        UART_tx( *string++ );
        //wait until transmission is finished
        while(tx_shift_reg);  //<=====  stuck here....
    }
}

So it thinks that tx_shift_reg is never getting cleared.

 

So look into why that might be:

  • what should be clearing it?
  • why is that not happening?

 

It is declared as volatile, isn't it ... ?

 

https://www.avrfreaks.net/forum/tutcoptimization-and-importance-volatile-gcc

 

 

avrcandies wrote:
Why do you need that?

If your chip has debug, why would you not use it?!

 

But, agreed, to answer the problem of #16 - the oscilloscope is the tool for that job.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

in #26, awneil wrote:
So it thinks that tx_shift_reg is never getting cleared.

 

So look into why that might be:

  • what should be clearing it?
  • why is that not happening?

 

It looks like Cliff might already have answered that right back at the start of the thread:

in #6, clawson wrote:
If you don't have the interrupt handler this is not going to happen

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Andy, he said that was just an omission from posting - see the complete code in #8

 

The obvious way to proceed if using debugWire to me would therefore seem to be to put a breakpoint in the top of that ISR and see (a) is it even hit (ie has the timer interrupting been correctly configured and enabled) and (b) if it reaches the ISR what path does it take through it? As the interrupts occur do the bits in tx_shift_reg slowly move >> and if they do why does it never reach the tx_shift_reg==0 state which would break it from the while() wait loop?

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

From Post#7

ISR(TIMER0_COMPB_vect)
TIMSK |= (1<<OCIE0B);

 

You are using COMPB interrupt vector and enabling the interrupt on the OCF0B Flag while the datasheet specifies OCF0A.

 

11.7.2 Clear Timer on Compare Match (CTC) 8-bit Mode   (ATtiny461A Datasheet - 8197C–AVR–05/11)

In Clear Timer on Compare or CTC mode, see Table 11-3 on page 76, the OCR0A Register is
used to manipulate the counter resolution.

 

Also

An interrupt can be generated each time the counter value reaches the TOP value by using the
OCF0A Flag.

 

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

 

Oh....Chuck is right that the OCR0B cannot be used for Compare match for CTC mode.  Only OCR0A is used for CTC mode. When I change the code to the OCR0A, the scope output is shown as attached file. (I still cant embed image in the media browser, always error). But the output from the serial terminal show only black background "?"

 

Somehow, the reading value is not correct.  I attached the output of the terminal as well. 

 

Actually i wanted to use OCR0B because my OCR0A already used for millis counting.  

  

 

 

Attachment(s): 

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

ki0bk in Post#22 wrote:

Could this be a simple case of the clock/8 fuse setting causing the baud rate to not be what the OP expects it to be?  

 

Can you read out and post the fuse settings for the  ATTiny461A?

 

Also, Please post the current source code.

 

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


This is the code.

#define F_CPU 8000000UL

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

// change these to use another pin
#define TX_PORT PORTB
#define TX_PIN  PINB0
#define TX_DDR  DDRB
#define TX_DDR_PIN DDB0

volatile uint16_t tx_shift_reg = 0;


void UART_tx(char character)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //if sending the previous character is not yet finished, return
   //transmission is finished when tx_shift_reg == 0
   if(local_tx_shift_reg){return;}
   //fill the TX shift register witch the character to be sent and the start & stop bits (start bit (1<<0) is already 0)
   local_tx_shift_reg = (character<<1) | (1<<9); //stop bit (1<<9)
   local_tx_shift_reg &=~(1<<0);//start bit
   tx_shift_reg = local_tx_shift_reg;
   //start timer0 with a prescaler of 8
   TCCR0B |= (1<<CS01) ;
   
}

void UART_tx_str(char* string){
    while( *string ){
        UART_tx( *string++ );
        //wait until transmission is finished
        while(tx_shift_reg);
    }
}

void UART_init(){
   //set TX pin as output
   TX_DDR |= (1<<TX_DDR_PIN);
   TX_PORT |= (1<<TX_PIN);
   //set timer0 to CTC mode
   // TCCR0A = TCW0 | ICEN0 | INCC0 | ICES0 | ACIC0 | - | - | CTC0
   //            0  |  0    |    0  |     0 |  0    | 0 | 0 |   1
   TCCR0A = (1<<WGM00);//for attint461A
   //enable output compare 0 B interrupt
   
   // TCCR0B = |- | -| - | TSM | PSR0 | CS02 | CS01 | CS00
   //          | 0|0 | 0 |  0  | 0    | 0    |  1   | 0    //8
   //if 16MHz divide by 64, timer will clock at 250K Hz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 250 K = 26
   
   //use internal 8MHz, timer will clock at 1MHz 
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 1M = 104
   
   
   TIMSK |= (1<<OCIE0A);
   //set compare value to 26 to achieve a 9600 baud rate (i.e. 104µs)
   //together with the 16MHz/64 = 250kHz timer0 clock
   //IF use internal 16MHz, use precaler of 16. 
   /*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
     to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
     increasing or decreasing the value by 1 or 2 */
   OCR0A = 104;//i change to 103 also the same.
   //enable interrupts
   sei();
}

int main(void)
{
   UART_init();

   while(1)
   {
    UART_tx_str("U\n");
    _delay_ms(100);
   }

   return 0;
}

//timer0 compare A match interrupt
ISR(TIMER0_COMPA_vect)
{
   uint16_t local_tx_shift_reg = tx_shift_reg;
   //output LSB of the TX shift register at the TX pin
   if( local_tx_shift_reg & 0x01 )
   {
      TX_PORT |= (1<<TX_PIN);
   }
   else
   {
      TX_PORT &=~ (1<<TX_PIN);
   }
   //shift the TX shift register one bit to the right
   local_tx_shift_reg >>= 1;
   tx_shift_reg = local_tx_shift_reg;
   //if the stop bit has been sent, the shift register will be 0
   //and the transmission is completed, so we can stop & reset timer0
   if(!local_tx_shift_reg)
   {
      TCCR0B = 0;
     // TCNT = 0;
   }
}

 

 

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

 

Ummmm why didn't you show the clock settings  ?  we don't want ot see spien, we want to see the clock selections!!

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Jul 22, 2021 - 08:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


This one ?

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

It should be very easy to spit out some characters on the uart with no more than 10 lines of code.  Even in asm , it might only be 2 dozen instructions to set up  & send out a little test stream.

 

Actually I dug around and found some simple examples....perhaps the port direction need set too, but you can see, there is not much to it....at least to get the ball rolling

setup_uart:ldi r16, 5  ; write correct clock divider value
	  out UBRR, r16
          ldi r16, 0b00011000 ;set Rx and Tx enable bits
          out UCR, r16 ; write them to the UART Control Register

tx_uart:  in r17, USR
          sbrs r17, UDRE   ;check if ok/ready to send something
          rjmp tx_uart
          ldi R16, 'Q'  ;send out QQQQQ forever
          out UDR, r16
          rjmp tx_uart 

That's more or less all that's needed to start spitting something (anything!) out the uart to see it do something

 

Don't start off by making a task of a few lines so short & simple turn into pages and pages of stuff & fluff.  ...Concentrate on making actual progress.  Rememebr, evrything you type is a chance for a typo.

 

 

Well, obviously , you prob want to turn off the divide by 8---why do you want to run the AVR at 1 MHz?  Also, as mentioned, you make a big mistake by starting with the ratty internal oscillator...might work...might not...so if you get no results...who knows (if it does work, then claim your prize).

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. Jul 22, 2021 - 08:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

But there is no UART in this ATTiny461A. 

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

 

hamisu wrote:
I still cant embed image in the media browser, always error

Did you try to paste the image - as noted in Tip #1 ?

 

 

awneil wrote:
if it's a digital scope, use it's trace capture facility - far better than a photo!

So it is a digital scope - but you didn't do that?

 

But the output from the serial terminal show only black background "?"

So what character do you think it should be?

 

Have you analysed your scope trace and asked yourself:

  • What, exactly, is the actual baud rate there? [1]
  • What character does that trace represent?

 

The Sparkfun tutorial linked in Tip #2 shows you how to "read" the UART waveform ...

 

EDIT

 

[1] your scope probably has features to easily measure the pulse widths (possibly also frequency);

 

Also, see the Hint in #17 (also #22) on how to get a nice, regular waveform ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jul 22, 2021 - 08:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

hamisu wrote:
But there is no UART in this ATTiny461A. 

So, again, why on earth did you choose that chip if your project needs a UART ?

 

EDIT

 

But it does have USI:

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jul 22, 2021 - 08:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hold on. Your fuses say "int RC" and "ckdiv8". The first selects 8MHz, the second divides it by 8. So your AVR is running at 1MHz. Therefore do not use:

#define F_CPU 8000000UL

However I don't think this is the root of the problem as I think the only thing using F_CPU is going to be:

   while(1)
   {
    UART_tx_str("U\n");
    _delay_ms(100);
   }

So it just means there will be an 800ms delay between transmission attempts rather than 100ms. Not fatal.

 

However it did make me study the timer set up. The first thing that is confusing is this:

   // TCCR0B = |- | -| - | TSM | PSR0 | CS02 | CS01 | CS00
   //          | 0|0 | 0 |  0  | 0    | 0    |  1   | 0    //8
   //if 16MHz divide by 64, timer will clock at 250K Hz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 250 K = 26

   //use internal 8MHz, timer will clock at 1MHz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 1M = 104

The first part of the comment is confusing, talking about a 16MHz clock. Don't leave "dead" comments that are wrong. It just misleads the maintenance engineer. The second part of the comment has all the signs of being right but then the actual OCR setting is not found after this. So that part of the comment is in the wrong place. You may say that is OK but then you have:

   //set compare value to 26 to achieve a 9600 baud rate (i.e. 104µs)
   //together with the 16MHz/64 = 250kHz timer0 clock
   //IF use internal 16MHz, use precaler of 16.
   /*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
     to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
     increasing or decreasing the value by 1 or 2 */
   OCR0A = 104;//i change to 103 also the same.

So at the end is where OCR0A is finally set to the right 104 as explained in the (right part) of the previous comment, but this OCR0A setting is proceeded by comment nonsense that once again talks about the calculation for 16MHz.

 

So in summary I'd suggest:

void UART_init(){
   //set TX pin as output
   TX_DDR |= (1<<TX_DDR_PIN);
   TX_PORT |= (1<<TX_PIN);
   //set timer0 to CTC mode
   // TCCR0A = TCW0 | ICEN0 | INCC0 | ICES0 | ACIC0 | - | - | CTC0
   //            0  |  0    |    0  |     0 |  0    | 0 | 0 |   1
   TCCR0A = (1<<WGM00);//for attint461A
   //enable output compare 0 B interrupt

   //use internal 8MHz, timer will clock at 1MHz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 1M = 104
   OCR0A = 104;//i change to 103 also the same.

   TIMSK |= (1<<OCIE0A);

   //enable interrupts
   sei();
}

Except that even that is "wrong". Don't bury the setting of the global I bit in SREG (that is sei()) within a peripheral init function like UART_init(). Bring the sei() out to main():

int main(void)
{
   UART_init();

   // all peripherals now configured so enable interrupts...
   sei();

   while(1)

This way, if you start to use other peripherals you can call there XXX_init() functions in any order but only when they are all complete do you enable interrupts. Otherwise if you had UART_init() being called before some other ADC_init() or SPI_init() or whatever it would have the nasty consequence of enabling interrupts before that other peripheral had finished configuring its own interrupt.

 

Anyway that is not the actual problem either.

 

But this is:

   tx_shift_reg = local_tx_shift_reg;
   //start timer0 with a prescaler of 8
   TCCR0B |= (1<<CS01) ; 

The comment on this TCCR0B setting is exactly right. Using CS01 does use a /8 prescaler whereas CS00 does not. But the /8 that was being used is all part of that old 16MHz calculation. They worked out the right OCR0A value for 16MHz but it also relied on the timer being run at 1/8th F_CPU speed and that is still happening. 

 

So just make this:

   tx_shift_reg = local_tx_shift_reg;

   //start timer0 with a prescaler of 1
   TCCR0B |= (1 << CS00) ;

and then the OCR0A = 104 value should deliver 104us interrupts.

 

(but I still think you should use a micro that has a UART if your project is based around the use of a UART!!)

Last Edited: Thu. Jul 22, 2021 - 08:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But there is no UART in this ATTiny461A 

Ah, I see again, my bonehead reading,  I was just glancing at the code & forgot the beginning.   I'm Thinking why so much length to spit out some char!.

Maybe so much commentary becomes blinding.  Calling everything Uart...leads the unwary to a wrong conclusion!

 

If you kill the divide by 8, you may finally have your stroke of luck

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

From  Post#32

void UART_init(){
   //set TX pin as output
   TX_DDR |= (1<<TX_DDR_PIN);
   TX_PORT |= (1<<TX_PIN);
   //set timer0 to CTC mode
   // TCCR0A = TCW0 | ICEN0 | INCC0 | ICES0 | ACIC0 | - | - | CTC0
   //            0  |  0    |    0  |     0 |  0    | 0 | 0 |   1
   TCCR0A = (1<<WGM00);//for attint461A
   //enable output compare 0 B interrupt
   
   // TCCR0B = |- | -| - | TSM | PSR0 | CS02 | CS01 | CS00
   //          | 0|0 | 0 |  0  | 0    | 0    |  1   | 0    //8
   //if 16MHz divide by 64, timer will clock at 250K Hz
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 250 K = 26
   
   //use internal 8MHz, timer will clock at 1MHz 
   //To get 9600 baud rate, which is 1/9600 = 104 usec
   //Count Value = 104us x 1M = 104
   
   
   TIMSK |= (1<<OCIE0A);
   //set compare value to 26 to achieve a 9600 baud rate (i.e. 104µs)
   //together with the 16MHz/64 = 250kHz timer0 clock
   //IF use internal 16MHz, use precaler of 16. 
   /*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
     to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
     increasing or decreasing the value by 1 or 2 */
   OCR0A = 104;//i change to 103 also the same.
   //enable interrupts
   sei();
}

 

You are showing a "div by 8" for TCCR0B to result in 1MHz  to the counter.

But the Fuse LOW.CKDIV8 fuse is checked so the 8MHZ is already divided by 8 for 1MHz clock

so your counter gets a 125KHz clock instead of a 1MHz clock.

 

Your can change TCCR0B to "div by 1"  or you can reprogram the fuses to uncheck the LOW.CKDIV8 fuse.

 

Also, since you are using the internal 8MHz RC oscillator, you may need to calibrate it.

 

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

avrcandies wrote:
If you kill the divide by 8, you may finally have your stroke of luck
Well that would get over the TCCR0B thing but you'd just be removing one of the /8s to have it put back in another. I'd sort of the CS01 versus CS00 thing first and then worry about CKDIV8 later.

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


Finally it work. The clock shall not divide by 8.  Sorry for my stupidity.

 

I can get my scope to save the data out because the storage external and disk management not activated as shown below. even I plu in the usb drive and restart.

I also try using USB wire at the back, it does not shown any internal save files as well. 

 

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

Finally it work. The clock shall not divide by 8.  Sorry 

That has caught just about everyone...in fact we wear a badge of honor & special pin for experiencing it.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

hamisu wrote:
I can get my scope to save the data out because the storage external and disk management not activated as shown below. even I plu in the usb drive and restart.

Oh well - you tried.

 

I'd suggest that it's worth pursuing this; being able to capture traces is a Really Useful Thing - not just for forum posts.

 

I've found Rigol support to be pretty helpful - have you contacted them?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I brought the Rigol from a second hand seller equipment seller shop.  The Model is Rigol DS1102D which suppose to have Logic Analyser. But there is no LA  cable, I thought the cable is cheap but finally found the cable is very expensive.    

 

One question I wish to ask since the data transfer is "U", will I be able to see the Binary code of "U" in the oscilloscope ?  Or I need to have Logic Analyser ? 

 

 

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

I brought the Rigol from a second hand seller 

Still worth an email to Rigol support.

 

hamisu wrote:
since the data transfer is "U", will I be able to see the Binary code of "U" in the oscilloscope ? 

If you're just using it as an oscilloscope, then it will just show you the voltage levels vs time.

 

But you can easily decode that manually - see the linked tutorial.

 

You would have to study the User Manual to see if it can do Async Serial Decode on the scope analogue channel inputs.

 

Manuals can be downloaded online: https://int.rigol.com/ - see the 'Support' tab

 

See also: https://www.rigolna.com/contact-us/ - even though I'm outside the US, they have been helpful.

 

EDIT

 

I have found that mine will sometimes not "like" a particular USB stick - so have you tried some different ones?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Jul 22, 2021 - 11:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

That looks like two characters were sent, "U" and a control character ACK (0x06)

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"