SOLVED: ATTiny87 LIN/UART pitfall

Go To Last Post
55 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I am having a problem here with an ATTiny87.

It sometimes doesn't start. Well actually most of the times it doesn't start (maybe 1 out of 20 attempts). Software seems to be ok; it is running fine when started from the debugger and is pretty simple anyway.

I first thought it is the oscillator. 8MHz crystal; 15pF. With fuses set to 3..8MHz the voltage swing (Peak-Peak) on XTAL1 was only about 1 Volt so I changed the fuses to 8..16MHz. Did not make a change but voltage swing now is about 1.2V. Can anybody confirm that this is enough?

I also experimented with various brownout level settings. Interestingly the Atmel tools allow you to use settings that are reserved in the data sheet. What I have now is 2.7V which I believe should work.

Fuses are: Ext.: 0xff, High: 0xdd, Low: 0xdf. This means: SPIEN enabled, Brownout detection 2.7V, no clock divide, External crystal osc. 8..16MHz, 16384C... (the rest is cut off by the Atmel tools; I believe it is 4.1ms startup time; but I'm not sure here either because the last selection here creates an invalid fuse setting according to the data sheet).

Supply voltage rises from 0 to 3.3V in about 7ms. Is that fast enough? Data sheet says min. 0.01V/ms.

Reset is connected to VCC via a 5k resistor; connecting it directly doesn't seem to make a difference.

When I apply a short external reset pulse it starts fine every time.

Only thing that I can think of is there are external components on the SPI pins (resistors to LEDs). Could that prevent the startup? Throuble here is that if I disable the SPIEN I do not have access for programming any more.

Kind Regards,
Hagen

This topic has a solution.
Last Edited: Mon. Jun 23, 2014 - 09:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did a bit more experimenting in the meantime:

- tried another board: same result.
- reduced power supply impedance (more caps): same result
- tried internal oscillator: same result
- tried different startup times (0, 64ms): same result
- tried faster VCC rise time: starts every time! (rise time here appr. 60us to 3.3V)

Does anybody have the tiny87 running using it's own internal reset with similar VCC rise times (2V/ms)? And would it be possible to share the fuse settings?

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

Maybe it's not the chip but the code??

Can you post a schematic of the board?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Maybe it's not the chip but the code??

Can never rule that out. But it runs fine when started from the debugger. And it starts fine everytime I assert an external reset (see above). So I think it's unlikely.

js wrote:
Can you post a schematic of the board?

Sure. 5K reset pull-up is soldered externally into X2-X3.

When measuring the supply voltage I noticed that when the board is not powered VCC is about 0.5V (!) which would be above Atmel Reset spec. This is caused by LEDs generating electricity. But even in darkness (VCC==0V) it doesn't start; so this is the not the problem.

Attachment(s): 

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

That's a lot of LEDs - is the PSU up to it?

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

48mA worst case? Yes PSU can handle that. I had also written earlier supply goes to 3.3V in 7ms.

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

You should never read the clock signal at XTAL1. Even with a 10x probe. The probe load will alter the drive. Read signal at XTAL2 pin.

It is a mystery why anyone would use a crystal for a LED display. Especially since you only want 8MHz.

I note that your SUT is 16k+0ms. Surely you should choose 16k+64ms. Thi will ensure the AVR does not start until you have power.

Oh, and your power supply needs to be able to supply all those LEDs ok.

David.

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

Ok, I may have mixed up XTAL1 and XTAL2; I definitely measured on the drive pin. Should I see close to 3V there? Maybe incorrect caps had been used.

But this is not the problem here; as I wrote before same happens with the internal oscillator (btw. Atmel worst case spec for internal oscillator is simply not good enough for running a serial interface; therefore the crystal).

The SUT0 and SUT1 settings are bit 4 and 5 in the low fuse byte. So 0b1101111 is SUT0-1 and SUT1-0 which is 14k cycles + 4.1ms according to table 4-5 in the 03/14 datasheet. I tried all other combinations as well apart from the SUT0-1 SUT1-1 setting which are reserved (the Atmel tools actually allow you to set them; unfortunately I do not know which value of delay because it is cut off).

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

The reserved setting seems to work (SUT0-1 SUT1-1).

But why don't the others work? Should not the brownout detection (enabled here) catch that if the power supply is not up?

And what is the situation with the 0.01V/ms risetime specification? I am factor 200 above, so why no reset even with 16384 cycles, 4.1ms with internal oscillator?

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

Use [url]http://www.engbedded.com/fusecalc[/url]. It is far more intuitive than AS6.
OTOH, I think you can stretch the Dialog Window in AS6. Try it, and see for yourself.
Personally, I think it is a bad design for Dialogs to be too small for the regular info.

Yes, XTAL2 is a different pin to XTAL1. If you are running at 3.3V, I would expect a reasonable 3V square wave.

Ah-ha. I did not spot the UART interface. Quite honestly, the 8MHz RC should be fine for the UART. However, you will need to adjust for 3.3V and check the calibration too.

Since you will have a program and test phase in production, I don't see this as a problem. 99% of chips will not need recalibrating. The 1% that do will take a little longer. But think about it. You have saved $0.20 on your parts bill.

I doubt if an LED display is going to use its UART very often. You can always adjust the calibration at runtime. Then you are wasting punter's time by 500ms as a one-off instead of your production test time.

Oh, I will give you a medal if you can work fuses out from the data sheet. I prefer something human.

David.

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

Are the serial pins connected to anything when your testing? I once had two mega's interconnected to each other via the two serial lines, the master mega could turn on/off the power to the slave mega, but the idle high on the serial port pins would keep the slave alive, so had to also disable the USART pins and set them low to prevent this "feedthru" power from the slave when I wanted to power down.
Try disconnecting your serial connections and see what happens.

JC

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

hugo_habicht wrote:
The reserved setting seems to work (SUT0-1 SUT1-1).

But why don't the others work? Should not the brownout detection (enabled here) catch that if the power supply is not up?

And what is the situation with the 0.01V/ms risetime specification? I am factor 200 above, so why no reset even with 16384 cycles, 4.1ms with internal oscillator?

16384 cycles @ 0.125us = 2.048ms
so you have a startup of 2.048+4.1 = 6.148ms

you stated earlier that your VCC was not valid until 7ms.

I really can't see that an LED display is going to worry about using 64ms to startup.

Yes, I suppose that a BOD should catch a bad VCC but it seems a very bad design choice. Especially since BOD is supposed to work with a running AVR.

David.

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

hugo_habicht wrote:
I also experimented with various brownout level settings. Interestingly the Atmel tools allow you to use settings that are reserved in the data sheet. What I have now is 2.7V which I believe should work.
Note that the BOD may release as low as 2.5V, which is technically too low for 8 MHz (minimum 2.7V).

Try running at 1 MHz by programming CKDIV8, just to see if it helps. If it does, it suggests BOD is on the low side and you're starting up out-of-spec.

hugo_habicht wrote:
The reserved setting seems to work (SUT0-1 SUT1-1).
How do you figure those are reserved? They aren't. With CKSEL0=1, SUT[1:0]=01 gives 16K+(14+4.1ms) and SUT[1:0]=11 gives 16K+(14+65ms).

hugo_habicht wrote:
But why don't the others work? Should not the brownout detection (enabled here) catch that if the power supply is not up?
How are you measuring Vcc rise? Use a fast scope, look for ringing.

Does your app drive LEDs immediately after reset? Just for trouble-shooting, try adding a delay before hand, or better yet use the watchdog to sleep for 500 ms.

Is C3 your bypass cap? Is it close to the MCU package?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Ok, I don't see 3V drive; but that is a different problem. internal oscillator doesn't start either.

Datasheet says +-10% on internal oscillator. So no good. And $0.20 for the crystal is cheaper than cal in test.

Uart is needed all the time because there the LED on/off commands are coming in :wink:

The device data sheet is the primary source of information I am getting from Atmel. Their tools (AS4/AS6) are secondary which I normally avoid particularly because they are windows based. And I certainly would never use any third party tools that somebody threw out there on the www for design purposes.

In this case (if fuse is 0xff for 64ms) the datasheet is faulty. Happens.

But lets not get distracted from the real problem. Why is the device not starting?

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

Hmmm.... while I was typing slowly other people posted some interesting points.

@jccordill: good point; I am aware of that and driving pins come from the same supply; so can't bias the circuit. But the LEDs do actually without any external supply!

@david: "so you have a startup of 2.048+4.1 = 6.148ms"
good point. But after 6ms my supply is way beyond 2.7 and the 7 were on the very pessimistic side. I double checked; about 5.5 to get to 3.0V.

Still you are right the margin is way too small; my fault here. The 4.1ms settings in the data sheet were actually 0 and the 64ms I tried as well were in reality 4.1ms. The 64ms (reserved setting in DS) now work fine.

@joeymorin: ok, 2.5V worst case is too low although I rebuild the software for 1MHz and tried it with div8; made no difference. But then minimum spec. for 1MHz is also 2.7V.

LEDs do nothing after reset; no current drawn here and voltage going up nicely (so far as you can see with 1GHz bandwidth). CAP is as close as I could get it; nice ground plane on the board too.

I think I'm happy enough; 64ms work and maybe Atmel can have another look at their data sheet.

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

Why not use 16k+64ms ?

If you are finding that 16k+64ms does not work, please say so.

This would be an interesting problem that would be worth investigating.

Oh, IMHO the http://www.engbedded.com/fusecalc is a lot more useful than Atmel's AS6 offering.
AS4 GUI was fine for choosing fuses, but has got many other failings.

You have your own opinions. I can only suggest that you try other tools. First of all, I suggest that you simply try stretching the AS6 window.

David.

p.s. if it is intersting, I would try it for myself on a real tiny167. I don't have a tiny87.

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

hugo_habicht wrote:
In this case (if fuse is 0xff for 64ms) the datasheet is faulty.
Huh?

hugo_habicht wrote:
But then minimum spec. for 1MHz is also 2.7V.
Nope. 1.8V.

Quote:
I think I'm happy enough; 64ms work and maybe Atmel can have another look at their data sheet.
I think you should ;)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Which data sheet is that? Mine is dated 03/14. Is there a newer version? Apologies then; but I do not download data sheets every week....

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

ARGGGHHH. Stupid. I clicked on the link and it went to the internal osc startup; the xtal is two pages further down. :oops:
If you can read you certainly have an advantage.
Thanks for all the help! Appreciated!

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

Quote:
I don't see 3V drive
You won't unless you have full swing oscillator mode enabled which is not available on the Tiny87 AFAIK.

If the problem was on another older chip I would have said to select full swing oscillator mode.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

joeymorin wrote:
Nope. 1.8V.

Datasheet says 2.7 to 5.5V operation. I cannot see 1.8V anywhere. I'm using the ATinty87-A15XZ.

@John: can you confirm about 1.2V on the drive pin then? I checked on other CPU types; found same value there.

The problem still persists. Even with 64ms settings it didn't start up (customer presentation, of course).

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

Quote:
The problem still persists. Even with 64ms settings it didn't start up (customer presentation, of course).

Seriously, this deserves investigation.

Please give full details of fuses, VCC curve, hardware layout, power supply and decoupling components.

David.

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

hugo_habicht wrote:
Datasheet says 2.7 to 5.5V operation. I cannot see 1.8V anywhere.
Latest datasheet is Rev. 8265D–AVR–01/2014, but all the datasheets say the same thing w.r.t. speed grade.

Page 1:

In the datasheet, Atmel wrote:
Speed Grade:
0 – 4 MHz @ 1.8 – 5.5V
0 – 8 MHz @ 2.7 – 5.5V
0 – 16 MHz @ 4.5 – 5.5V
However:
Quote:
I'm using the ATinty87-A15XZ
This is the first time you've mentioned you're using the automotive grade device, which is indeed rated down to 2.7V only.

But as you've noted it's unlikely this is the root of the problem.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I tried all kinds of fuse settings without success. External reset circuits did not help either. It seems that the IC is hanging after reset. Debugging is not possible due to debug wire and reset being on the same pin.

What I have now is a delay loop at the beginning of main(). That seems to fix the problem although I have no idea why.

At the beginning of main() is simply I/O port initialisation, timer init and then uart init.

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

I don't follow your 'delay loop'. If the AVR clock is not running, it can't execute any code ---- time wasting or otherwise!

Post some minimal code that exhibits your problem. Together with your actual fuse values.

Then readers can try to reproduce the problem.
I am sure that I have a tiny167 somewhere.
It will not be automotive.

I could investigate startup times etc.

David.

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

hugo_habicht wrote:
What I have now is a delay loop at the beginning of main(). That seems to fix the problem although I have no idea why.
This still suggests to me that power is taking too long to stabilise.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

david.prentice wrote:
I don't follow your 'delay loop'. If the AVR clock is not running, it can't execute any code ---- time wasting or otherwise!

Hi David,

exactly! That's what I figured already. Trouble is I cannot see if it is executing code or not and where it is hanging due to the debugwire limitations.

Fuse settings (see also my first post) are now: ext-ff high-df low-fd.

Starting from the debugger code works every time. From power up it doesn't. When I inserted a 'for (i = 0; i < 20000; ++i);' loop at the beginning of main it starts. Maybe there is a supply problem and it doesn't like enabling ports, timers and uart too fast. Can't see anything suspicious on the scope though.

@joeymorin: please read my previous posts wrt supply rise time.

Regards,
Hagen

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

Here a few plots. Green is supply measured at pin 15, yellow is oscillator.

Nominal voltage after the processors starts (@65ms) is 3.30 volts. The worst glitch in the supply I found is about 150mV. That still leaves 450mV margin to 2.7V.

Attachment(s): 

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

hugo_habicht wrote:
@joeymorin: please read my previous posts wrt supply rise time.
I did. 'Fast rise time' != 'stable'.

hugo_habicht wrote:
Here a few plots. Green is supply measured at pin 15, yellow is oscillator.
Sure looks to me like the oscillator isn't stable yet.

In TEK0003.png, the slight dip in Vcc likley represents the end of reset and the start-up of the core. It's about 65 ms after the sharp onset of Vcc and the associated start of POR.

It seems to me that the clock isn't yet stable. Or is this an 'aliasing' artefact from the 25ms/div timebase?

I would want to rule out the oscillator as the cause. As part of testing, I would remove the crystal and caps and instead supply a solid external 8 MHz clock. How does this affect the problem?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Clock is stable when supply reaches 3 Volts. What you see is aliasing together with peak detection (attempt) in the scope.

I had tried internal oscillator already (see earlier posts) and divide by 8 as well. The 20k loop works a treat; not perfectly happy but there is no point spending more time on this; this is only a minute part of the system and I have to move on.

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

hugo_habicht wrote:
I had tried internal oscillator already.
That is not an external clock.

Although the RC oscillator should be stable after only a few swings, I would still want to rule out the clock source.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

joeymorin wrote:
...I would still want to rule out the clock source.
We can rule it out. I checked it. Crystal oscillator is running and stable long before processor starts.

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

We can definitely rule out the oscillator. Just checked an old board that does not work. The LED anode multiplexing is actually running so it seems it is not receiving anything from the UART or the port init for the cathode outputs did not work.

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

Ok, it's the UART. I put in a default LED pattern. This comes up. But when the 20k delay is missing the UART does not receive anything (bitstream is arriving at RxD).

Is there anything to watch out for with this combined LIN/UART?

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

hugo_habicht wrote:
We can definitely rule out the oscillator. Just checked an old board that does not work. The LED anode multiplexing is actually running so it seems it is not receiving anything from the UART or the port init for the cathode outputs did not work.
That does not rule out the oscillator, but it does at least get you a step closer to solving the problem... except that you've decided to 'move on' ;)

In the face of an unstable system clock I would expect some components of the core and some peripherals to fail before others. Most AVR require a clock (internal or external) which has less than 2% variation in the frequency from one cycle to the next. Operating outside this constraint is operating outside of spec and will lead to unpredictable behaviour. Although the datasheet for the '87 doesn't specify this restriction, most other datasheets do. I expect the '87 is nevertheless subject.

The internal oscillator and the crystal oscillator modes should easily meet these criteria, provided sufficient start-up time is configured via CKSEL and SUT, but there is no mechanism to monitor or enforce it in the '87.

I agree that it is unlikely, but if this were my app I would not consider it ruled out yet. I certainly wouldn't ship with a kludge like a delay loop on startup unless I knew exactly what was going on and why the delay mitigated the problem.

The fact that you see the anode multiplexing in operation tells you that the core is running, at least partially. That may help you. Apart from the test I propose with a known stable external clock source, I would conduct another test to confirm that the startup delay configured by CKSEL and SUT is in fact taking place:

int main(void) {
  DDRB |= (1<<PB0);
  PORTB |= (1<<PB0);
  while (1);
}

Put your scope on Vcc and PB0, and a weak external pull-down on PB0. How long between Vcc rise and PB0 rise? The plots you posted suggest to me that the 65 ms delay is indeed taking place, but that dip in Vcc could be something else. This would confirm it.

Assuming i is a volatile int, the for loop you posted compiles into an 18-cycle loop. At 8 MHz x 20000 passes that's about 45 ms of additional delay. Have you tried other delays? BTW, why not just use _delay_ms()?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Quote:

Is there anything to watch out for with this combined LIN/UART?


I haven't used that particular subsystem, but with a "real" USARt it isn't uncommon to get a false start bit at startup.

Beyond that, it depends how you handle farming errors and such.

IME, it isn't a bad thing to apply the pullup to the RXD line immediately at AVR startup along with other pin direction and state. Then, I always use a delay for as long as the app is comfortable with to allow external devices to settle. Most common delay for me is 100ms. This allows slow external devices (can you say "character LCD"?) to stabilize before attempting to use.

>>Then<< I start the USART, with the RXD line held high for that time.

I've lost track--have you posted UART code? Are you filtering against framing and other errors? Could you be trying to act on an incoming byte that has a framing error?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ok, I got a step further.

In case of the RxD pin being low when the UART is initialised it seems to hang; i.e. does not receive any characters after that.

I changed the software in the main processor to have the pin high and that fixes the problem (same way as the delay; 20k was a very lucky guess).

The RxD low is a break condition. Do I have to clear that before it operates again? I could not find anything in the data sheet.

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

@joeymorin

Startup is 62ms.

@Theusch

Any garbage received at startup should not do any harm. I simply fill a buffer with up to 6 characters (colour per led) and then it is processed when a newline is received. So after a few seconds it would receive a new message and display the correct colours. But it does nothing. Just sits there.

I can post the UART driver code and main(); can't rule out that I am not initialising the thing correctly. Haven't used this LIN/UART before.

Last Edited: Mon. Jun 23, 2014 - 08:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The LIN is pretty easy to use if you just want it as a regular UART.

It would be wise to post a minimal program that exhibits your 'problem'.

Quite honestly, your scope traces don't make much sense to me. You should get a reasonable signal on XTAL2. Or on CLKOUT if available.

David.

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

The Uart hardware driver:

/****************************************************************************/
/* main rs232 interface functions */
/****************************************************************************/

/*--------------------------------------------------------------------------*/
/* initialise rs232 controller */
/* */
/* ctl - controller number */
/* bdr - baud rate (software uarts have to have identical baudrate) */
/* if baud rate is 0 the controller will be disabled */
/* dat - number of databits (5, 6, 7 or 8) */
/* par - type of parity ('n', 'o' or 'e') */
/* rcv - pointer to receive interrupt function or NULL */
/* trx - pointer to transmit interrupt function or NULL */
/* */
/* return value: */
/* */
/* 0 - in case of error */
/* other - controller number if successful */
/*--------------------------------------------------------------------------*/
u08 rs2_ini(u08 ctl, u32 bdr, u08 dat, chr prt, intfcn rcv, intfcn trx)
{
u16 ubrr;

if (bdr)
{
if (ctl == RS2CTL0)
{
ubrr = SYSFRQ / bdr / 52 - 1;

PRR &= ~MSK(PRLIN);
LINBTR = 52 | MSK(LDISR);
LINBRRH = (ubrr >> 8) & 0x00ff;
LINBRRL = ubrr & 0x00ff;
LINCR = 0b00001111;
}
else
ctl = 0x00;
}
else
{
if (ctl == RS2CTL0)
LINCR = 0x00;
else
ctl = 0x00;
}

return ctl;
}

/*--------------------------------------------------------------------------*/
/* check if receive character is available */
/* */
/* ctl - controller number */
/* */
/* return value: */
/* */
/* 0 - no character received */
/* other - receive character available */
/*--------------------------------------------------------------------------*/
u08 rs2_rcv(u08 ctl)
{
u08 ret;

ret = 0;

if (ctl == RS2CTL0)
{
if (LINSIR & MSK(LRXOK))
--ret;
}

return ret;
}

/*--------------------------------------------------------------------------*/
/* read character received */
/* */
/* ctl - controller number */
/* */
/* return value: */
/* */
/* EOF - no character available */
/* other - character received */
/*--------------------------------------------------------------------------*/
int rs2_inp(u08 ctl)
{
int ret;

ret = EOF;

if (rs2_rcv(ctl))
{
if (ctl == RS2CTL0)
ret = LINDAT;
}

return ret;
}

And main():

/****************************************************************************/
/* main program */
/****************************************************************************/
extern int main(void) __attribute__ ((__naked__));
int main(void)
{
u08 row; /* row counter */
tmrtyp tmr; /* timer */
u08 val;
u08 len; /* length of received string */

/*----- initialise ---------------------------------------------------------*/
hdw_ini();
tmr_ini();
rs2_ini(INDCTL, INDBDR, 8, 'n', NULL, NULL);

/*----- test initialisation ------------------------------------------------*/
#ifdef TST
tst_ini(0);
tst_prn("main()\n");
tst_prn(" hello, anybody out there?\n");
#endif

row = 0;
tmr = tmr_val();
len = 0;
while (1)
{
/*----- wait mux time ------------------------------------------------------*/
while (tmr_val() - tmr < (1.0 / MUXFRQ / TMRQNT))
{
if (rs2_rcv(INDCTL))
{
val = rs2_inp(INDCTL);
if (len < INDMAX)
buf[len++] = val;
if (val == '\n')
{
for (len = 0; len < INDMAX; ++len)
{
val = buf[len];
if (val == 'r')
col[len] = RED;
else if (val == 'g')
col[len] = GRN;
else if (val == 'b')
col[len] = BLU;
else if (val == 'y')
col[len] = RED | GRN;
else if (val == 'm')
col[len] = RED | BLU;
else if (val == 'c')
col[len] = GRN | BLU;
else if (val == 'w')
col[len] = RED | GRN | BLU;
else
col[len] = 0;
}
len = 0;
}
}
}

/*----- row off ------------------------------------------------------------*/
if (row == 0)
dig_out(INDROW0, INDROWOFF);
else if (row == 1)
dig_out(INDROW1, INDROWOFF);
else if (row == 2)
dig_out(INDROW2, INDROWOFF);

/*----- next row -----------------------------------------------------------*/
if (++row >= ROWMAX)
row = 0;

/*----- column drivers -----------------------------------------------------*/
val = col[row + 0];

if (val & RED)
dig_out(INDCOLR0, INDCOLACT);
else
dig_out(INDCOLR0, INDCOLOFF);

if (val & GRN)
dig_out(INDCOLG0, INDCOLACT);
else
dig_out(INDCOLG0, INDCOLOFF);

if (val & BLU)
dig_out(INDCOLB0, INDCOLACT);
else
dig_out(INDCOLB0, INDCOLOFF);

val = col[row + 3];

if (val & RED)
dig_out(INDCOLR1, INDCOLACT);
else
dig_out(INDCOLR1, INDCOLOFF);

if (val & GRN)
dig_out(INDCOLG1, INDCOLACT);
else
dig_out(INDCOLG1, INDCOLOFF);

if (val & BLU)
dig_out(INDCOLB1, INDCOLACT);
else
dig_out(INDCOLB1, INDCOLOFF);

/*----- row active ---------------------------------------------------------*/
if (row == 0)
dig_out(INDROW0, INDROWACT);
else if (row == 1)
dig_out(INDROW1, INDROWACT);
else if (row == 2)
dig_out(INDROW2, INDROWACT);

/*----- next timer value ---------------------------------------------------*/
tmr += 1.0 / MUXFRQ / TMRQNT;

}

return 0;
}

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

After peeking at the datasheet, I wonder what LINERR says when you are in your problem situation.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

david.prentice wrote:
It would be wise to post a minimal program that exhibits your 'problem'.

The problem happens with the code above when the RxD pin is held low externally when rs2_ini() is called. I was enabling all pull-ups immediately after reset but the pin was driven low by the other processor (break).

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

theusch wrote:
After peeking at the datasheet, I wonder what LINERR says when you are in your problem situation.

Good point. I just can't see a simple way of reading this register. I don't want to enable debugwire; I'm still having nightmares from previous attempts trying to disable it again.

Would you say LRXOK is cleared again in case of LFERR and LOVRERR being set?

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

Somthing like that seems to happen. When I short the RxD pin after it started up properly it hangs again, so it seems LRXOK is never set.

So it seems this LIN/UART does not behave like a normal UART.

Last Edited: Mon. Jun 23, 2014 - 08:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Would you say LRXOK is cleared again in case of LFERR and LOVRERR being set?


In retrospect, would you have been better off with e.g. Tiny1634 or Mega48? :twisted:

I only took a quick pass at the datasheet. As with a normal AVR8 USART, the flags are lost once you look at the data register. Beyond that you'll have to work through the datasheet about enabled errors and such.

Is there no tutorial or app note or such on using this beastie as a normal USART?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

E.g.

Quote:
• Bit 3 – LERR: Error Interrupt
It is a logical OR of LINERR register bits. This bit generates an interrupt if its respective
enable bit - LENERR - is set in LINENIR.
–0 = No error,
– 1 = An error has occurred.
The user clears this bit by writing 1 in order to reset this interrupt. Resetting LERR also
resets all LINERR bits.
In UART mode, this bit is also cleared by reading LINDAT.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
In retrospect, would you have been better off with e.g. Tiny1634 or Mega48? :twisted:

Believe it or not, the tiny87 was the ONLY one I could find with the minimum number of I/O required, a (pseudo)-UART and that would fit onto the board (dimensions were fixed):

Attachment(s): 

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

theusch wrote:
Is there no tutorial or app note or such on using this beastie as a normal USART?

Not that I know of. There is AVR304 which pretty much contains nothing. Otherwise I could not find anything. Maybe Atmel should create one: "Pits, traps and mines in the LIN/UART" :-).

The data sheet is very vague about the UART functions; looks to me as if the UART part was added as an afterthought by adding a few gates.

I changed the code. It seems once an error flag is set the LRXOK is cleared. I now clear LERR and the UART receives bytes even after a short to ground on the RxD pin.

Problem finally solved. Thank you very much to all contributors in this thread!

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

hugo_habicht wrote:
Problem finally solved.
Great news.
Quote:
Thank you very much to all contributors in this thread!
I might suggest you change the thread subject to:
Quote:
[SOLVED] ATtiny87 LIN pitfalls
...or some such. This will help others in your position find a solution more quickly.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Quote:

Believe it or not, the tiny87 was the ONLY one I could find with the minimum number of I/O required, a (pseudo)-UART and that would fit onto the board (dimensions were fixed):

Isn't Tiny2313 the same size? And a real USART. And more usable pins.

But you are down the road now...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ummm--the Tiny1634 is also 20 pins. (I thought it might be more..) Two real USARTs. Lots of toyz for a Tiny.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Pages