How do i fetch data from UDRn on Mega2560? - c

Noob question:
I'm trying to learn about UART on an ARDUINO. I wrote some very simple code and for some reason, i can't make the receive() function work. I don't think it fetches the data from the UDR register. I'm using a small OLED display and i want to print the received data to it. No data is being printed to the display, when i run the code.
I connected the ports TX1 and RX1 with a wire on the board.
I tried finding youtube videos and have been reading alot. Appearently not enough.
Any ARDUINO expert who knows what to do?
#include <avr/io.h>
#include "ssd1306.h"
#include "I2C.h"
#include <stdio.h>
#include <util/delay.h>
void initOLED();
void initUART1();
void receive();
void transmit();
int main(void)
{
I2C_Init();
initOLED(); //initialiaze OLED
while (1)
{
transmit();
receive();
}
}
void initOLED()
{
I2C_Init();
InitializeDisplay();
clear_display();
}
void initUART1(void)
{
DDRD = 0x08; //TXD1 set to output
UBRR1L = 51; //Baudrate 19200
UBRR1H = 0; //upper four bits of baudrate
UCSR1A = 0x02; //Double speed mode
UCSR1B = 0x18; //Enable receive and transmit
UCSR1C = 0x06; //1 stop bit, 8-bit, no parity
}
void transmit()
{
char b = 'a';
while(!(UCSR1A & (1<<UDRE1))); //wait for an empty UDR register
UDR1 = b; //load character in register
}
void receive()
{
int Y = 0; //Y coordinate for cursor on the display
char d;
while(!(UCSR1A & (1<<RXC1))); //wait for unread data in the receive buffer
d = UDR1; //set UDR register in character d
sendCharXY(d, 1, Y); //send character to display
}

It looks like you never call initUART1().

Related

uart between atmega328p (C) and Feather m0 (Arduino) receive

I want to send data from my ac/gy via atmega328p to a feather m0 module. The atmega is programmed in C using the following github code: https://github.com/YifanJiangPolyU/MPU6050
And the Arduino code for receiving data within the LoRa module is shown below:
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
byte strArray[30];
int i = 0;
if(Serial1.available()>0) {
while (Serial1.available()>0){
strArray[i] = Serial1.read();
i++;
}
// send the 6 bytes payload to LoRaWAN port 7 --> now port 1
LMIC_setTxData2(1, strArray, sizeof(strArray), 1);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage HIGH //optional: for confirmation
}
}
}
// Next TX is scheduled after TX_COMPLETE event.
//delay(60000);
void loop() {
os_runloop_once();
}
However, I can't seem to receive anything and can't send a "char array" to the gateway using the LMIC function apparently, so trying to receiving data within a byte array instead. Any help or tips regarding this is greatly appreciated. I'll also include the main.c code for the atmega328P down here below:
#define F_CPU 16000000UL
#define BAUD 9600
#include <inttypes.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/setbaud.h>
#include <avr/interrupt.h>
#include <math.h>
#include "mpu6050.h"
#include "mpu6050_reg.h"
#include "i2c.h"
#include "uart.h"
void timer_setup();
void get_time(double* dt);
volatile double count;
const double unit_t = 8/16000000;
int main(void){
sei();
uart_init();
i2c_init();
DDRB |= _BV(5);
uint8_t ret;
int16_t accel_buff[3], gyro_buff[3];
double accelX, accelY, accelZ;
double gyroX, gyroY, gyroZ;
double biasX, biasY;
double phi_accel, theta_accel;
double phi_innov, theta_innov;
double phi_est, theta_est;
double phi_prev, theta_prev;
double dt;
char s[30];
// initialize & test MPU5060 availability
ret = i2c_start(MPU6050_ADDRESS+I2C_WRITE);
if(~ret){
PORTB |= _BV(5);
_delay_ms(200);
PORTB &= ~(_BV(5));
}
mpu6050_init();
timer_setup();
// find gyro bias
biasX = 0;
biasY = 0;
uint8_t i;
for(i=0; i<20; i++){
mpu6050_read_gyro_ALL(gyro_buff);
biasX += gyro_buff[0];
biasY += gyro_buff[1];
}
biasX = biasX/20*(3.14159/180)/1000/32768;
biasY = biasY/20*(3.14159/180)/1000/32768;
// initialization for Kalman filter
double P = 0.0;
double Q = 0.001;
double R = 0.03;
double Pp, K;
mpu6050_read_accel_ALL(accel_buff);
phi_prev = atan2(accelY, accelZ); // row
theta_prev = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
for(;;){
get_time(&dt);
mpu6050_read_accel_ALL(accel_buff);
mpu6050_read_gyro_ALL(gyro_buff);
// acceleration (m/s^2)
accelX = accel_buff[0]*9.8*2/32768;
accelY = accel_buff[1]*9.8*2/32768;
accelZ = accel_buff[2]*9.8*2/32768;
// gyro rate (rad/s)
gyroX = gyro_buff[0]*(3.14159/180)/1000/32768;
gyroY = gyro_buff[1]*(3.14159/180)/1000/32768;
gyroZ = gyro_buff[2]*(3.14159/180)/1000/32768;
// estimation
phi_est = phi_prev + dt*(gyroX - biasX);
theta_est = theta_prev + dt*(gyroY - biasY);
Pp = P+Q;
// innovation
phi_accel = atan2(accelY, accelZ); // row
phi_innov = phi_accel - phi_est;
theta_accel = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
theta_innov = theta_accel - theta_est;
// Kalman gain
K = Pp/(Pp+R);
// correction
phi_prev = phi_prev + K*phi_innov;
theta_prev = theta_prev + K*theta_innov;
P = (1-K)*Pp;
uart_putchar('\n');
_delay_ms(10);
uart_putdouble(phi_prev); //phi, row
uart_putdouble(theta_prev); //theta, pitch
uart_putdouble(dt);
//_delay_ms(10);
}
}//end of main
void timer_setup(){
TCCR1A = 0x00;
TIMSK1 |= _BV(TOIE1);
TCCR1B |= _BV(CS11);
TCCR1B &= ~( _BV(CS12) | _BV(CS10)); // prescaler=8
}
void get_time(double * dt){
cli();
uint8_t l = TCNT1L;
uint8_t h = TCNT1H;
uint16_t step = h<<8 | l;
*dt = (double)step*5e-7 + count*0.032768;
count = 0;
sei();
}
// timer 1 overflow interrupt handler
SIGNAL(TIMER1_OVF_vect){
count += 1;
}
Connect the board to the PC and check in the Arduino IDE Serial Monitor if you can get or send data.
If your serial communication doesn't work, you can check if you are past a point in execution by turning on the led on the board. Most development boards have at least 1, and with Arduino is just a matter of setting the pin as output and digitalWrite(LED_BUILTIN, 0) in setup, then digitalWrite(LED_BUILTIN, 1) at the point you want to check.
If your atmega328p is on an arduino board (e.g. uno, nano etc) you should check in the same way for it, too. Both the serial and past-the-point verification.
I'd to that, then rely on the serial for debugging for a while.
I'm curious, do you think the condition "if(Serial1.available()>0)" is true?

How do I produce a sawtooth waveform using c language?

This is my program with regards to DAC using PIC18F97J60. I am new to this and already struggling alot so please do not judge me.
#include <P18F97J60.h>
//#include <delays.h>
//#include "delays.c"
void SPI1init(void);
void SPI1out(char Code);
void SPI1init(void)
{
SSP1CON1 = 0b00100010; // Enable SPI, CKP=0, Master, Fosc/64
SSP1STATbits.CKE = 1; // CKE=1, (rising edge for shift register)
TRISCbits.TRISC3 = 0; // RC3 is SCk
TRISCbits.TRISC5 = 0; // RC5 is SDO
SPI1out(0x00);
}
void SPI1out(char Code)
{
SSP1BUF = Code; // Transmit
while(SSP1STATbits.BF==0); // Wait for END (Receipt Buffer Full)
Code = SSP1BUF; // Just read to clear BF
}
Diagram for the circuit: https://ibb.co/M1cChNB
Question of the assignment: https://ibb.co/rwz3kwP

Read a txt file from PC using UART - Atmega32A

I am a beginner in microprocessor programming. I created an array and sent datas using UART. I want to read a text file and create this array using datas in the text file with the simplest way possible. Any suggestion to proceed? Thanks in advance.
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 8000000UL // Clock freq
char flag = 0;
void usart_init(void){
UCSRA = 0x02;
UCSRB = 0x98; // Enable transmitter Enable receiver Enable Interrupt
UCSRC = (1<<UCSZ1) | (1<<UCSZ0); // set as 8 bit data, no parity bit and 1 stop bit.
UBRRH = 0x00;
UBRRL = 109;
}
int main(void){
usart_init();
while(1){
unsigned char array[5]={0x44,0xAA,0x33,0xBB,0x55};
for (int i=0;i<5;i++){
UDR = array[i];
UDR = 0xFF;
_delay_ms(100);
}
sei();
if(flag == 1)
{
flag = 0;
UCSRB = 0x98;
}
}
}
ISR(USART_RXC_vect){
UCSRB = (0<<RXEN)|(0<<TXEN)|(0<<RXCIE);
flag = 1;
}
You are working with a microcontroller so you can't handle a file directly. You had to code every value (copy & paste) in your source code.
unsigned char const array[5]={0x44,0xAA,0x33,0xBB,0x55};
You had to do this even for a large array.

AVR, UART, Proteus simulation, not all data displayed on virtual terminal

I am writing a code for a MCU until that will transmit data via UART (RS232).
[ATmega8A]
Currently, I am testing my code in Proteus:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <compat/twi.h>
#define FOSC 16000000 //Clock Speed
#define BAUD 9600 //Baud rate set to 9600
#define MYBRR FOSC/16/BAUD-1
void USART_Init (void)
{
UBRRH = (MYBRR >> 8); //Code for setting
UBRRL = MYBRR; //the baud rate
UCSRB = (1 << RXEN) | (1 << TXEN); //Enable receiver and transmitter
UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); //Frame format setting: 8 Data, 2 Stop bit
}
/* USART transmit function */
void USART_Transmit(unsigned char data)
{
while(!(UCSRA & (1 << UDRE))); //Wait until transmit buffer is empty
UDR = data;
}
/* USART receive function */
unsigned char USART_Receive(void)
{
while(!(UCSRA & (1 << RXC))); //Wait until data is received
return UDR; //Get the data from buffer and return it
}
and the test code in main:
int main(void)
{
unsigned char c;
while(1)
{
a = USART_Receive();
c = 10;
USART_Transmit(c);
_delay(10000);
}
}
In Proteus, the virtual terminal displays 0. However, I am expecting to see 10.
This is just one example, in general only the last digit/character is getting displayed on the virtual terminal.
I cannot explain this. Proteus bug or logic error?
Thank you for any advise.
UART data is sent only in ascii format...you have to convert the integer data to ascii format..use itoa() or do this one
int main(void)
{
unsigned char c;
unsigned char b;
while(1)
{
a = USART_Receive();
c = 10;
b=c;
b=c/10;
USART_Transmit(b+48);
b=0;
b=c%10;
USART_Transmit(b+48);
_delay(10000);
}
}

LCD shift right and shift left bugs

I have made a library for LCD with HD44780 controller in it, and from the datasheet I read that the code 0x18 will shift the entire display one position to the left, but when I made that, the display disappears.
I have also read that 0x1C shifts the entire display one position to the right but when I made it, the entire display shifts to left.
My code:
/*
* main.c
*
* Created: 11/14/2013 7:54:02 PM
* Author: A R M T
*/
#include <avr/io.h>
#define F_CPU 1000000UL
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#define LCD_DPRT PORTA //LCD DATA PORT
#define LCD_DDDR DDRA //LCD DATA DDR
#define LCD_DPIN PINA //LCD DATA PIN
#define LCD_CPRT PORTB //LCD COMMANDS PORT
#define LCD_CDDR DDRB //LCD COMMANDS DDR
#define LCD_CPIN PINB //LCD COMMANDS PIN
#define LCD_RS 0 //LCD RS
#define LCD_RW 1 //LCD RW
#define LCD_EN 2 //LCD EN
//*************************************************************
void delay_us(unsigned int d);
void lcdCommand(unsigned char cmnd);
void lcdData(unsigned char data);
void lcd_init(void);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_print(char *str);
//*************************************************************
void delay_us(unsigned int d)
{
_delay_us(d);
}
//*************************************************************
void lcdCommand(unsigned char cmnd)
{
LCD_DPRT = cmnd; //send cmnd to data port
LCD_CPRT &= ~(1<<LCD_RS); //RS = 0 for command
LCD_CPRT &= ~(1<<LCD_RW); //RW = 0 for write
LCD_CPRT |= (1<<LCD_EN); //EN = 1 for H-to-l pulse
delay_us(1); //Wait to make enable wide
LCD_CPRT &= ~(1<<LCD_EN); //EN = 1 for H-to-l pulse
delay_us(100); //Wait to make enable wide
}
//*************************************************************
void lcdData(unsigned char data)
{
LCD_DPRT = data; //send data to data port
LCD_CPRT |= (1<<LCD_RS); //RS = 1 for data
LCD_CPRT &= ~(1<<LCD_RW); //RW = 0 for write
LCD_CPRT |= (1<<LCD_EN); //EN = 1 for H-to-L pulse
delay_us(1); //wait to make enable wide
LCD_CPRT &= ~(1<<LCD_EN); //EN = 0 for H-to-L pulse
delay_us(100); //wait to make enable wide
}
//*************************************************************
void lcd_init(void)
{
LCD_DDDR = 0xFF;
LCD_CDDR = 0xFF;
LCD_CPRT &= ~(1<<LCD_EN); //LCD_EN = 0
delay_us(15000); //wait for init
lcdCommand(0x38); //init. LCD 2 line, 5 * 7 matrix
lcdCommand(0x0E); //display on, cursor on
lcdCommand(0x01); //clear LCD
delay_us(2000); //wait
lcdCommand(0x06); //shift cursor right
}
//*************************************************************
void lcd_gotoxy(unsigned char x, unsigned char y)
{
unsigned char firstCharAdr[] = {0x80, 0xC0, 0x94, 0xD4};
lcdCommand(firstCharAdr[y-1] + x - 1);
delay_us(100);
}
//*************************************************************
void lcd_print(char *str)
{
unsigned char i = 0;
while (str[i] != 0)
{
lcdData(str[i]);
i++;
}
}
//*************************************************************
int main(void)
{
lcd_init();
lcd_gotoxy(1,1);
lcd_print("Armia");
lcd_gotoxy(1,2);
lcd_print("Wagdy");
_delay_ms(1000 / 2);
lcdCommand(0x18); // Shift the entire display one position to the left
while(1);
return 0;
}
I meant that when I burned this code I excepected that aftr(1000 / 2) ms this output will shift to left
but what appears was(the word disappears instead of shifting left one postition)
Can any one help me in that problem please?!
I tried your code in proteus version 7.10 and shift left works fine
Note that you are using the _delay_us function with a variable parameter, that is not the correct way, it gives wrong delays and generates big hex file because it forces the float library to be included
delay.h manual
Note:
In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an
expression that is a known constant at compile-time. If these
requirements are not met, the resulting delay will be much longer (and
basically unpredictable), and applications that otherwise do not use
floating-point calculations will experience severe code bloat by the
floating-point library routines linked into the application.
Replace the code with a loop that calls the delay several times
while (d--)
{
_delay_ms(1);
}

Resources