UDR register cleared before reading data - serial-port

I am trying to simulate the uart using ATmega128. I have written this code in AVR STUDIO 4.
The PORTB0 is for used switch so that when it is pressed it is connected to 5v dc and it sends 'a' to uart1. at other times it is connected to ground. the reception of data is by interrupt.
Using debugger, when there is data in UDR1 and RXC1 is set, program jumps to ISR, and then UDR register is immediately cleared and nothing is retrieved. Can any one tell me why this happens?
Here is the code.
volatile unsigned char rxdata;
void uart_init(void)
{
UCSR1A = 0x00;
UCSR1B |= (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1); //0b10011000;
UCSR1C |= (1<<7)|(1<<UCSZ11)|(UCSZ10); //0b10000110;
UBRR1H = 0;
UBRR1L = 103; //9600 baud rate
}
ISR(USART1_RX_vect)
{
rxdata = UDR1;
PORTC = rxdata;
}
void putch(char data)
{
while(!(UCSR1A & 0x20));
UDR1 = data;
}
And the main program is
void port_init(void)
{
DDRC = 0xFF;
}
int main(void)
{
port_init();
uart_init();
sei();
while(1)
{
if (PINB & 0x01){
putch('a');
}
}
}

I had this once. In my case, setting the breakpoint before the flag was evaluated in the code cleared it, because The AVR Studio "read" the flag (as I had the flag register open). Setting the breakpoint AFTER the line where the flag was read, helped. In your case, set the breakpoint on line PORTC = rxdata;
To get a better debug feeling, I read the flag into a variable right at the beginning of the ISR and set the breakpoint right after this.
It's been some years since this happened and I'm not even sure if this was really the case. So, maybe you can verify this ;)

I took a look at the AVR Studio 4 help section. Regarding known simulator issues with respect to UART functions it states:
The UART/USART UDR register can only be modified from the application. Input via stimuli files or by modifying the I/O view etc is not possible.

Related

PORTB and INT external interrupts stucks the code

I am working on a project with PIC16F877 (using MPLABX). I use RB0 pin external interrupt and RB4 pin portb interrupt to detect zero cross detection. I did everything correct, in proteus simulation everything was okey. Then I set up the circuit on breadboard, the LCD wasnt displaying the numbers (just the white dots). I thought the problem is the RB0 and PORTB interrupt. I wrote a simple code just includeshe PORTB interrupt and LCD and simulated. Everything is okey until the interrupt occures, when interrupt comes the code stops. I am new to PIC, this is the code I wrote:
/*
* File: lcd_deneme_16f877a.c
* Author: BATUHAN
*
* Created on 28 Aral?k 2022 Çar?amba, 13:52
*/
#include <xc.h>
#include <stdio.h>
#include <stdint.h>
#pragma config FOSC = XT // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = ON // Data EEPROM Memory Code Protection bit (Data EEPROM code-protected)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = ON // Flash Program Memory Code Protection bit (All program memory code-protected)
#define _XTAL_FREQ 4000000
void __interrupt() interrpt()
{
if(INTF)
{
uint8_t dummy = PORTB; // Read PORTB to end mismatch condition
INTF=0;
RD0=RD0^1;
}
if(RBIF==1 && RB4==1)
{
uint8_t dummy = PORTB; // Read PORTB to end mismatch condition
RBIF=0;
RD0=RD0^1;
}
}
void main(void)
{
TRISD=0X00;
PORTD=0X00;
TRISB=0b00010001;
PORTB=0X00;
INTCON=0b11011000; // GIE PEIE TMR0IE INTE RBIE TMR0IF INTF RBIF
OPTION_REGbits.nRBPU = 1;
INTEDG=1;
int V=0;
while(1)
{
V++;
__delay_ms(200);
}
return;
}
I tried the PORTB and RB0 interrupts separately and the problem still occurs.
What could be the problem. Thanks in advance
This is because your program stucks in interrupt routine due to the lack of proper handling of interrupts. You don't seem to handle the INT interrupt at all. For RB interrupt-on-change (IOC), you have to handle it sort of a little different and end the mismatch condition before clearing the flag. According to the PIC16F877A Datasheet this how the IOC works and must be handled:
Four of the PORTB pins, RB7:RB4, have an interrupt-on-change feature. Only pins configured as inputs can cause this interrupt to occur (i.e., any RB7:RB4 pin configured as an output is excluded from the interrupt-on-change comparison). The input pins (of RB7:RB4)are compared with the old value latched on the last read of PORTB. The “mismatch” outputs of RB7:RB4
are OR’ed together to generate the RB port change interrupt with flag bit RBIF (INTCON<0>). This interrupt can wake the device from Sleep. The user, in the Interrupt Service Routine, can clear the interrupt in the following manner:
a) Any read or write of PORTB. This will end the mismatch condition.
b) Clear flag bit RBIF.
A mismatch condition will continue to set flag bit RBIF. Reading PORTB will end the mismatch condition and allow flag bit RBIF to be cleared.
So your interrupt service code should look like the following:
void __interrupt() interrpt()
{
if(RBIF && RB4)
{
volatile uint8_t dummy = PORTB; // Read PORTB to end mismatch condition
RBIF=0;
RD1=RD1^1;
}
else if(INTIF) {
INTIF = 0;
RD0 = !RD0; // Toggle D0 for INT interrupt
}
}
A friendly reminder
The proteus simulation is ok for some cases. However the simulation runs in ideal conditions. That's why you may not get the same expected behaviour in the real world conditions compared to proteus' ideal simulation conditions.
void __interrupt() interrpt()
{
if(RBIF)
{
PORTB; // Read PORTB to end the mismatch condition
RBIF=0;
if(RB4)
RD1=RD1^1;
}
else if(INTF) {
INTF = 0;
RD0 = !RD0; // Toggle D0 for INT interrupt
}
}

STM32Duino ADC does't give sampled data

I try original O-Scope project (PigOScope) without touchscreen based on STM32F103C8T6 Bluepill board, but got some problem:
I used newest rogerclarkmelbourne/Arduino_STM32 Core and downloaded
pingumacpenguin/STM32-O-Scope sketch. I compiled and uploaded it to the device via UART from 0x08000000 address. Then I started the device. The grid and coordinate lines were displayed on the screen. Also on the screen were displayed inscriptions below 0.0 uS/Sample etc... But any noise or pulse signal from PB1 on my Probe. Why the chart is not drawn?
Also I tried to log my steps in Usart in DMA activation code function:
void takeSamples()
{
// This loop uses dual interleaved mode to get the best performance out of
the ADCs
Serial.println("Init DMA");
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH1, DMA1_CH1_Event);
Serial.println("Enable DMA for ADC");
adc_dma_enable(ADC1);
dma_setup_transfer(DMA1, DMA_CH1, &ADC1->regs->DR, DMA_SIZE_32BITS,
dataPoints32, DMA_SIZE_32BITS, (DMA_MINC_MODE |
DMA_TRNS_CMPLT));// Receive buffer
Serial.println("Set DMA transfer");
Serial.println(maxSamples / 2);
dma_set_num_transfers(DMA1, DMA_CH1, maxSamples / 2);
dma1_ch1_Active = 1;
Serial.println("Enable the channel and start the transfer");
dma_enable(DMA1, DMA_CH1); // Enable the channel and start the transfer.
samplingTime = micros();
Serial.println(samplingTime);
while (dma1_ch1_Active); // SOME BUG OR WHAT.... PROGRAM STOP HERE!!!
samplingTime = (micros() - samplingTime);
Serial.println("Disable DMA");
dma_disable(DMA1, DMA_CH1); //End of trasfer, disable DMA and Continuous
mode.
}
Event handler for stop interrupt
static void DMA1_CH1_Event()
{
dma1_ch1_Active = 0;
}
Volatile flag to stop routine
volatile static bool dma1_ch1_Active = 0;
Program keep crushing on while loop i think... And program does't work beyond takeSamples() function.
Why program does't exit the loop?

Why does delay() cause my arduino to reset?

I am using an Arduino Uno, connected to a USB shield, a RFID shield(adafruit PN532), an LCD, EEPROM(24AA256) and a RTC module(DS1307). I will not post my code here because it is too large and it is separated in multiple files.
In my program, I realize that if my programs enters a certain functions, after entering function after function, if I use a delay() at the end of the function I am currently in, the arduino resets. An example of what I mean is below.
void a() { b(); }
void b() { c(); }
void c() { d(); }
void d()
{
lcd_string("Testing", 0x80);
delay(2000); <---- Arduino resets at the delay here
}
At first, I thought it was because my dynamic memory was at 80%, and when I compiled, they said the Arduino might have some stability issues. So I modified my code such that my dynamic memory is now 57%. Problem still exist.
I thought maybe the delay() function has some overflow or something, so I tried replacing the delay with the following code.
unsigned long timing;
timing = millis();
timing += 2000;
while(millis() < timing);
The Arduino still resets.
Next, I thought maybe because my arduino is connected to my PC, some serial pin might have been causing the reset, so I used an external Power to power up the arduino and disconnected the USB. The arduino still resets.
Next, I thought maybe Timer1 might have been crashing with the delay() function, although the delay function uses Timer0 so I disabled my Timer1 . The arduino still resets.
Is there any other possibilities that I am missing out? My program storage space is at 69% which I believe shouldn't be an issue.
Edit
Here is my code for Timer1 ISR
ISR(TIMER1_OVF_vect)
{
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 34286;// = (16*10^6) / (1*1024) - 1 (must be <65536)
TCCR1B |= (1 << CS12);
// enable timer compare interrupt
TIMSK1 |= (1 << TOIE1);
triggered = 1;
}
Any other interrupt of flags used are in the library header files.
I am using the following external libraries
USB Host shield library 2.0
Adafruit PN532 master
A little sample to come close to RAM corruption ...
#define MEM_PER_LEVEL 50
#define TRY_TO_SURVIVE 10
void KillMe(int level) {
byte dummy[MEM_PER_LEVEL];
for ( byte i = 0; i < MEM_PER_LEVEL; i++)
dummy[i]= i;
Serial.println(level);
delay(1000); // not sure why this would hurt more than others
if (level < TRY_TO_SURVIVE) KillMe(level+1);
for ( byte i = 0; i < MEM_PER_LEVEL; i++) {
if (dummy[i] != i) {
Serial.println(F("corruption happened"));
while(1) {} // HALT
}
}
if (level == 0)
Serial.println(F("survived"));
}
void setup() {
Serial.begin(9600);
KillMe(0);
}
void loop() { }
I had the same problem - wherever I put a delay in my setup function the Arduino would restart.
For me, the problem was an instance of SoftwareSerial with invalid pin numbers.
SoftwareSerial mySerial(30, 31);
Anyone else landing on this question should check their pin numbers are appropriate for the board they're targeting. Not sure why the crash only happens if a delay is called, would be interested if anyone has insight into this!

In Arduino, how do you write to port when port is a variable?

Examples of writing to a port seem to always use the port number as a constant, eg,
OCR2A = 180;
How do you write to the port when the port is unknown until run time. For example,
int port = (buttonPressed) ? 0x3b : 0x3c;
portWrite( port, 180 );
What I cannot find is the funtion portWrite(). Does something like that exist?
Robert's answer has some imprecise assertions and an incomplete answer.
Writing directly to port registers you can ruin other settings of the port and sometimes cause permanent damage to controller.
Can ruin other settings: true, you have to know what you are doing (for instance what pins are on the port you are manipulating, and know what are the functions you want to keep.
Can cause permanent damage: not really, or better not because of the port manipulation. If you wire a short circuit to ground and then set it as an output to 1, you can damage it whether you are using the port register or the digitalwrite. You have to be careful in both ways.
Now, returning to your problem, the enumeration is one way, but since the PORTB, PORTC, PORTD are just short name for values, you can set a variable and then use it to indirectly access it.
The type for this kind of variable is a volatile pointer to a byte (volatile means that write and read operations cannot be optimized by the compiler, since the value can change even between two operations):
volatile uint8_t *variablePortRegister;
You just have to load it with the address (so with the & symbol) of the register you want to change:
variablePortRegister = &PORTC;
then use the pointer to change the value
PORTC = 0x12;
becomes
(*variablePortRegister) = 0x12;
This is a short example. For it to work, connect a LED with resistor on arduino pin 5 (bit 5 of PORTD). The LED on the board (labeled L) is connected to pin 13 (bit 5 of PORTB).
The sketch will make one of the two leds blink for five times, then switch to the other. Only port manipulation instructions are used, and you can find that the way to read the port is the same as the one to write it.
volatile uint8_t *myportreg;
unsigned long lastTime;
uint8_t counter;
void setup() {
DDRB |= 0x20;
DDRD |= 0x20;
PORTB = 0;
PORTD = 0;
counter = 99; // trigger the register change immediately
}
void loop() {
if (counter >= 10)
{
counter = 0;
if (myportreg == &PORTD)
myportreg = &PORTB;
else
myportreg = &PORTD;
}
if ((millis() - lastTime) > 500)
{
lastTime = millis();
// change bit 5 of register
*myportreg = 0x20 ^ (*myportreg);
counter++;
}
}
EDIT: as Robert pointed out, it's much better to "use" just the pins you need (in this case, bit 5 of port B and D) rather than setting the whole port; this way you minimize the risk of screwing up something else. This edit is already included in the above code, so the code is correct
The port is a bit in one particular register. If you know the register and the position of the port in that particular register you can try this:
register = (1<<port) || register
to set the port to 1 and
register = (1<<port)^-1 && register
to set the port to 0.
Of course, you will need a switch somewhere to determine the register and the bit of the port in the register given the port name.

Dim LED over time in a even flow using Arduino

Im trying to figure out how to dim a led over time(time is defined by the user lets call it rampUp). Im using arduino with the adafruit breakout PWM-Servo-Driver (http://www.adafruit.com/products/815) with the library : https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
this breakout has 4095 steps (0-4095) so now my problem:
I want to be able to take a variable ( int minutes) and send that to a method that will dim a LED from 0 to 4095 in a equal light intensity increase for the period minutes. I want the increase to be incremented by 1 each time it increases.
So how do I write the method without using delay() ?
void dimLights(int rampUp){
// some code to regulate the increase of the third value in setPWM one step at a time over a period of rampUp(int in minutes)
led.setPWM(0,0,4095);
}
the reason for not wanting to use delay() is because it will pause/stop the rest of the program.
I actually implemented something close recently:
void loop() {
/* ... */
if (rampUp != 0)
led.setPWM(0,0,rampUp);
}
void led_update() {
// here you can prescale even more by using something like
// if (++global_led_idx == limit) {
// global_led_idx = 0;
++rampUp;
}
void start() {
TCCR1B |= _BV(WGM12);
// set up timer with prescaler = FCPU/1024 = 16MHz/1024 ⇒ 60ms
TCCR1B |= _BV(CS12) | _BV(CS10);
TCCR1B &= ~_BV(CS11);
// initialize counter
OCR1A = 0x0000;
// enable global interrupts
sei();
// enable overflow interrupt
TIMSK1 |= _BV(OCIE1A);
}
void TAGByKO_LED::stop() {
TIMSK1 &= ~_BV(OCIE1A);
rampUp = 0;
}
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK) {
led_update();
}
then you can call start() to start the timer, or stop() to stop it. You can read more documentation about the registers I've been using here and the ISR statement. Beware that it's one of the most tricky things of AVRs to really understand, and even then you'll always need to have a cheatsheet or the datasheet close by.
You may also use #sr-richie's solution with timers, but do only setup variables in the dimLights() function, and call led.setPWM() only within the loop().

Resources