I've a SAM4s Xplained and want to use the UART1 but can't find a example or help. I tried on my own but it doesn't work.
Here is my code so far:
conf_uart.h
#include "asf.h" //uart.h etc. included here
#include <sam4s_xplained.h>
#define UART_SERIAL_BAUDRATE 9600
#define UART_SERIAL_CHANNEL_MODE UART_MR_CHMODE_AUTOMATIC //UART_MR_CHMODE_NORMAL
#define UART_SERIAL_MCK 240000000UL //CHIP_FREQ_CPU_MAX (tired both!)
#define UART_SERIAL_MODE UART_MR_PAR_NO
void uart_custom_init(void);
conf_uart.c
#include "conf_uart.h"
uint8_t received_byte;
void uart_custom_init(void) {
sysclk_init();
const sam_uart_opt_t uart_console_settings = {
UART_SERIAL_BAUDRATE,
UART_SERIAL_CHANNEL_MODE,
UART_SERIAL_MCK,
UART_SERIAL_MODE
};
uart_init(UART1,&uart_console_settings); //Init UART1
uart_enable_rx(UART1); //Enable RX (receiving)
uart_enable_tx(UART1); //Enable TX (transmitting)
uart_enable(UART1); //Enable UART1
uart_enable_interrupt(UART1,UART_IER_RXRDY); //Interrupt reading ready
NVIC_EnableIRQ(UART1_IRQn);
}
void UART1_Handler() {
uint32_t dw_status = uart_get_status(UART1);
if(dw_status & UART_SR_RXRDY) {
uint8_t received_byte;
uart_read(UART1, &received_byte);
uart_write(UART1, received_byte);
}
}
I tried different things. As Example I activated the automatic echo, but I don't recieve anything on my Computer and I don't receive anything at my SAM4s.
Here is my working code:
Offline
conf_uart.h
#include "asf.h" //uart.h etc. included here
#define UART_SERIAL_BAUDRATE 9600
#define UART_SERIAL_CHANNEL_MODE UART_MR_CHMODE_NORMAL
#define UART_SERIAL_MODE UART_MR_PAR_NO
/* =============== UART1 =============== */ //(UART0 is defined but not UART1)
#define PINS_UART1 (PIO_PB2A_URXD1 | PIO_PB3A_UTXD1)
#define PINS_UART1_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define PINS_UART1_MASK (PIO_PB2A_URXD1 | PIO_PB3A_UTXD1)
#define PINS_UART1_PIO PIOB
#define PINS_UART1_ID ID_PIOB
#define PINS_UART1_TYPE PIO_PERIPH_A
#define PINS_UART1_ATTR PIO_DEFAULT
void uart_custom_init(void);
void sendViaUart(uint8_t data);
conf_uart.cpp
#include "conf_uart.h"
void uart_custom_init(void) {
sysclk_init();
// set the pins to use the uart peripheral
pio_configure(PINS_UART1_PIO, PINS_UART1_TYPE, PINS_UART1_MASK, PINS_UART1_ATTR);
//enable the uart peripherial clock
pmc_enable_periph_clk(ID_UART1);
const sam_uart_opt_t uart1_settings =
{ sysclk_get_cpu_hz(), UART_SERIAL_BAUDRATE, UART_SERIAL_MODE };
uart_init(UART1,&uart1_settings); //Init UART1 and enable Rx and Tx
uart_enable_interrupt(UART1,UART_IER_RXRDY); //Interrupt reading ready
NVIC_EnableIRQ(UART1_IRQn);
}
void sendViaUart(uint8_t data) {
while (!(UART1->UART_SR & UART_SR_TXRDY));
uart_write(UART1, data);
}
void UART1_Handler() {
uint32_t dw_status = uart_get_status(UART1);
if(dw_status & UART_SR_RXRDY) {
uint8_t received_byte;
uart_read(UART1, &received_byte);
sendViaUart(received_byte);
}
}
best regards
Leo
closed -
The problem is that the UART on this board Sam4S Explained Pro is not mapped to PB2A and PB3A. The UART is mapped to PB2A and PA22A. It took me a long day to figure this out because it's wrong in the documentation.
You might also like this page:
It contains the setup for SAM4S uart and lots of other examples.
ASF Source Code Document It uses USART0, and i know you want to use USART1. But still a good reference.
Hope this helps
Related
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
I'm not really that familiar with C so please bear with me...
I'm writing some simple code for a watchdog timer on an Atmel Tiny 85, developing in AtmelStudio. I want to access the clock() function of the time.h library:
#include <time.h>
.....
void main() {
clock_t start = clock();
....
}
Unfortunately the compiler complains that clock is an undefined reference. Every code example I have looked up on the web seems to be doing what I am doing. Is there some fundamental thing I am missing? Thanks!
Here is the full code:
#define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <time.h>
#include <stdio.h>
#include <avr/wdt.h>
#include <stdint.h>
#include <util/atomic.h>
#define LED_PORT PB1
#define RST0_PORT PINB3
#define RST1_PORT PINB4
#define HEARTBEAT PINB0
volatile int HEARTBEAT_RECEIVED;
#define CLOCKS_PER_SECOND 1000000;
const int TIMEOUT_PERIOD = 120; //reset raspberry pi after this many seconds
void set_output();
void set_input();
void set_interrupts();
void run_timer(clock_t start);
void restart_raspberry_pi();
int main(void)
{
clock_t start;
HEARTBEAT_RECEIVED = false;
//Configure IO pins
set_output();
set_input();
PORTB &= ~(1 << RST0_PORT); // Set pin low (common ground pin for pi reset)
PORTB &= ~(1 << RST1_PORT); // Set pin low (initialize for no pi reset)
//Configure and enable interrupts
set_interrupts();
while (1) {
sei();
start = clock();
run_timer(start);
}
return (0);
}
void run_timer(clock_t start) {
double time_elapsed;
do {
_delay_ms(1000);
if (HEARTBEAT_RECEIVED) { //If heartbeat detected, reset timer.
HEARTBEAT_RECEIVED = false;
return;
}
time_elapsed = ( clock() - start ) / CLOCKS_PER_SECOND;
} while (time_elapsed < TIMEOUT_PERIOD);
restart_raspberry_pi(); //Timeout period has elapsed, reset the pi
}
ISR(PCINT0_vect) {
//Indicate that a heartbeat has been received
HEARTBEAT_RECEIVED = true;
}
void restart_raspberry_pi() {
cli();
PORTB |= (1 << RST1_PORT); // Set pin high (sets RUN high to reset)
_delay_ms(500);
PORTB &= ~(1 << RST1_PORT); // Set pin low (release reset control)
}
void set_output()
{
//The DDxn bit in the DDRx Register selects the direction of this pin.
//If DDxn is written logic one, Pxn is configured as an output pin.
//If DDxn is written logic zero, Pxn is configured as an input pin.
//PORTB = (0<<PB0) | (1<<PB3);
DDRB = (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1); // Set pins as output.
}
void set_input()
{
DDRB |= (0<<DDB0); // set pin 0 as input. Added |=.
}
void set_interrupts()
{
GIMSK |= (1 << PCIE); // pin change interrupt enable
PCMSK |= (1 << PCINT0); // pin change interrupt enabled for PCINT0
}
#Shawn had it right....I dove into the time.h library code available to me and apparently:
Section 7.23.2.1 clock()
The type clock_t, the macro CLOCKS_PER_SEC, and the function clock() are not implemented. We
consider these items belong to operating system code, or to application code when no operating
system is present.
So I guess that's a lesson for me. Thanks for the help.
So I am having a tough time setting up my SPI, and getting it to work with the LSM330 device to read accelerometer data. I'm simply setting up the SPI system, and trying to use that to read the WHO_AM_I_A register to confirm that it is working and all I'm getting back is 0xff rather than 0x40.
Here is my code:
main.c
#include <avr/io.h>
#include "LSM330.h"
#include "spi.h"
#include "CLK.h"
#include "accel.h"
int main(void) {
//set clock
set32MhzClock();
//first set SPI slave selects for accel gyro to false(high)
PORTF.OUTSET = PIN4_bm | PIN3_bm;
//set serial system of SPI
PORTA_OUTCLR = PIN4_bm;
//init SPI
spi_init();
//reset LSM330 accel by sending 0x01 to CTRL_REG4_A
accel_write(0x01, CTRL_REG4_A);
//trying to read from WHO_AM_I_A reg
uint8_t whoAreYou = accel_read(WHO_AM_I_A);
printf(whoAreYou);
}
accel.h
#include "LSM330.h"
#include "spi.h"
void accel_write(uint8_t reg_addr, uint8_t data) {
//make slave select signal LOW
PORTF_OUTCLR = PIN3_bm;
//set sensor_sel
PORTF_OUTSET = PIN2_bm;
//first write reg_addr, w/ RW=0 and MS=0
uint8_t writeResult = spi_write(reg_addr);
//then write data byte
spi_write(data);
return;
}
spi.h
void spi_init(void) {
//set correct pins as outputs and inputs
PORTF.DIRSET = PIN7_bm | PIN5_bm | PIN4_bm | PIN3_bm; //SCK, MOSI, SSG, SSA as outputs
PORTF.DIRCLR = PIN6_bm; //MISO as input
//set up SPI as master
SPIF.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_3_gc | SPI_PRESCALER_DIV16_gc;
//clear spi interrupt flag by reading spsr and spdr
SPIF_STATUS;
SPIF_DATA;
return
}
uint8_t spi_write(uint8_t dataIn) {
//write data
SPIF.DATA = dataIn;
//wait for transmission to complete
while(!(SPIF_STATUS & SPI_IF_bm));
return SPIF.DATA;
}
uint8_t spi_read(vodi) {
return spi_write(0xFF);
}
And that's all I have. Have tried many things, and can't seem to get this thing to work. It seems like SPI is working because it's not getting stuck up in any of the while loops when writing data.
Without going too much into the details, there is definitely something wrong here:
//reset LSM330 accel by sending 0x01 to CTRL_REG4_A
accel_write(0x01, CTRL_REG4_A);
But the declaration of your function is as follows:
void accel_write(uint8_t reg_addr, uint8_t data)
It seems you are setting register 0x01 to value of CTRL_REG4_A.
I am trying to get readings from 3 rotary encoders (KY-040) and send values via UART.
I am using Arduino-Mega 2560 board but due to requirements reason I am programming it in C.
But when I try to get the reading from encoder I get random numbers.
And it only works with every even number of rotation and program gets stuck at odd rotation. (it seems little odd)
Can anybody please suggest what is wrong with my code.
P.S. I am new working with micro controller.
#define F_CPU 16000000 //Clock Speed
#define UART_BAUD 9600
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "uart.h"
#include <stdlib.h>
volatile unsigned int encPosZ=0;
void sendEncValue(unsigned int value){
char string[5];
itoa(value, string, 10);
uart_puts(string);
}
// main
int main(void)
{
//disable all interrupts
cli();
uart_init(UART_BAUD_SELECT(UART_BAUD,F_CPU));
DDRE &=~ (1 << PE4);
DDRE &=~ (1 << PE5);
/* set pull-up enabled */
PORTE |= (1 << PE4)|(1 << PE5);
EIMSK |= (1 << INT4)|(1 << INT5);
/* INT4 - falling edge, INT5 - rising edge */
EICRB|= (1<<ISC41)|(1<<ISC51)|(1<<ISC50);
// Enable the Global Interrupt Enable flag
sei();
uart_puts("Started... ");
while(1)
{
_delay_ms(5);
}
return 0;
}
//INT4 interrupt
ISR(INT4_vect)
{
if(!bit_is_clear(PINE, PE5)){
encPosZ++;
}else{
encPosZ--;
}
sendEncValue(encPosZ);
}
//INT5 interrupt
ISR(INT5_vect)
{
if(bit_is_clear(PINE, PE4)){
encPosZ++;
}else{
encPosZ--;
}
sendEncValue(encPosZ);
}
MCUCR is not used for the purpose you are using it. In fact, most of its bits are read-only.
Perhaps you meant to use EICRA and EICRB. These are the registers to set rising and falling edges.
I'm attempting to set up UART communication with a GPS module but keep running into some communication error. The GPS sends a packet approximately once a second to the SAM4E16E micro, which should be trigger an interrupt and read in the data. I have two UARTS which are configured like this
conf_uart.h
#include "asf.h" //uart.h etc. included here
#define UART_SERIAL_BAUDRATE 4800
#define UART_SERIAL_CHANNEL_MODE UART_MR_CHMODE_NORMAL
#define UART_SERIAL_MODE UART_MR_PAR_NO
#define UART_SERIAL_STOP_BIT US_MR_NBSTOP_1_BIT
/* =============== UART0 =============== */
#define PINS_UART0 (PIO_PA9A_URXD0 | PIO_PA10A_UTXD0)
#define PINS_UART0_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define PINS_UART0_MASK (PIO_PA9A_URXD0 | PIO_PA9A_URXD0)
#define PINS_UART0_PIO PIOA
#define PINS_UART0_ID ID_PIOA
#define PINS_UART0_TYPE PIO_PERIPH_A
#define PINS_UART0_ATTR PIO_DEFAULT
/* =============== UART1 =============== */
#define PINS_UART1 (PIO_PB2A_URXD1 | PIO_PB3A_UTXD1)
#define PINS_UART1_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
#define PINS_UART1_MASK (PIO_PB2A_URXD1 | PIO_PB3A_UTXD1)
#define PINS_UART1_PIO PIOB
#define PINS_UART1_ID ID_PIOB
#define PINS_UART1_TYPE PIO_PERIPH_A
#define PINS_UART1_ATTR PIO_DEFAULT
conf_uart.c
#include "conf_uart.h"
void uart_custom_init_1(void) {
// set the pins to use the uart peripheral
pio_configure(PINS_UART1_PIO, PINS_UART1_TYPE, PINS_UART1_MASK, PINS_UART1_ATTR);
//enable the uart peripherial clock
pmc_enable_periph_clk(ID_UART1);
const sam_uart_opt_t uart1_settings =
{ sysclk_get_cpu_hz(), UART_SERIAL_BAUDRATE, UART_SERIAL_MODE };
uart_init(UART1,&uart1_settings); //Init UART1 and enable Rx and Tx
uart_enable_interrupt(UART1,UART_IER_RXRDY); //Interrupt reading ready
NVIC_EnableIRQ(UART1_IRQn);
}
uart_custom_init_0(void)
{
// 1. Enable UART peripheral clock
//2. Enable the required PIO's
pio_configure(PINS_UART0_PIO, PINS_UART0_TYPE, PINS_UART0_MASK, PINS_UART0_ATTR);
pmc_enable_periph_clk(ID_UART0);
// 3. call init
const sam_uart_opt_t uart0_settings =
{ sysclk_get_cpu_hz(), UART_SERIAL_BAUDRATE, UART_SERIAL_MODE };
uart_init(UART0,&uart0_settings); //Init UART1 and enable Rx and Tx
// read on interrupt
uart_enable_interrupt(UART0,UART_IER_RXRDY); //Interrupt reading ready
NVIC_EnableIRQ(UART0_IRQn);
}
void UART1_Handler() {
uint32_t dw_status = uart_get_status(UART1);
if(dw_status & UART_SR_RXRDY) {
uint8_t received_byte1;
uart_read(UART1, &received_byte);
read_buffer[read_buffer_index] = received_byte;
read_buffer_index++;
}
}
void UART0_Handler() {
uint32_t dw_status = uart_get_status(UART0);
if(dw_status & UART_SR_RXRDY)
{
uint8_t received_byte0;
uart_read(UART0, &received_byte);
read_buffer[read_buffer_index] = received_byte;
read_buffer_index++;
}
}
UART1 works perfectly. UART0 Only fires roughly once per packet, and is not even getting the first byte in the packet (should be 36, receives 16). As far as I can tell they are identical. The chip is working, I can see it transmitting on the scope. I'm basically fresh out of ideas.
I'm having problems with serial communication. I've connected an AtMega644 to a serial LCD which takes 9600 8N1. I just get garbage. By garbage I'm just getting some U,P,T and # instead of the desired "U". I'm using the internal 8Mhz RC Osc with the fuses listed below. I suspect a timing issue but I'm not sure where I went wrong. I added a blinking LED and the timing looks right (eyeball and digital stopwatch). Any help is appreciated.
avrdude -pm644 -cavrisp2 -Pusb -b2400 -u
-Uflash:w:ImpactTarget.hex:a
-Ulfuse:w:0xe2:m
-Uhfuse:w:0xd8:m
-Uefuse:w:0xff:m
#define F_CPU 8000000
#define BAUDRATE 9600
#define UBRRVAL (F_CPU/(BAUDRATE*16UL)) -1
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
/***************************************************** USART_Init()
*
*
**/
void USART_Init () {
//Set baud rate
UBRR0H = (unsigned char)(UBRRVAL>>8); //high byte
UBRR0L = (unsigned char) UBRRVAL; //low byte
//Asynchronous normal speed
UCSR0A = (0<<U2X0);
//Enable Transmitter and Receiver and Interrupt on receive complete
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
//page 186 Set asynchronous mode,no parity, 1 stop bit, 8 bit size
UCSR0C= (0<<UMSEL00)| (0<<UMSEL01)| //Async
(0<<UPM00) | (0<<UPM01) | //Parity None
(0<<USBS0) | //Stop bits 1
(0<<UCSZ02) | (1<<UCSZ01) |(1<<UCSZ00); //8 Bits
//enable interrupts
sei();
}
/******************************************** send_btye
* sends one byte to serial port
**/
void send_byte (char data) {
while ( ! (UCSR0A & (1<<UDRE0)) )
/* NOOP */;
UDR0 = data;
}
/**
* _delay_ms has a short time so this is an extension
*/
void delay_ms (int time) {
for (int i = 0; i < time; i++) {
_delay_ms(1);
}
}
/****************************** main *********/
int main () {
USART_Init();
DDRA = 0xff;
for (;;) {
send_byte('U');
delay_ms(500);
PORTA ^=_BV(PA0);
}
return 0;
}
Your UBRRVAL doesn't fully parenthesize its expression so when it is expanded in a context like UBRRVAL >> 8 the >> 8 does not apply the way you expect.
I think you're right - it's probably a timing issue: the internal RC oscillator is usually much too imprecise to use for USART.
I would try to attach an external crystal (and set the fuses correspondingly) and see if it helps.
this is exactly what took 3 days of my project time, just try to set Baudrate at (9600) and set the (X2) option for Baudrate. it should work.