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.
Related
I am trying to configure a PIC24FJ512GA610 to use SPI to interface with an ADC module. As such, I am configuring it in two-wire mode (only SCK and SDI, CS controlled by ports). Below is the relevant code I am using to configure the SPI. A header file contains most definitions:
// SPI3 is used to read from 22-bit ADC tied to RTDs
// SPI3CON1L
#define SPI3EN 0<<15 // SPI Enable Pin
// unimplemented
#define SPI3SIDL 0<<13 // Stop when CPU is in idle mode
#define SPI3DSSDO 1<<12 // Disable SDO (no data sent to ADC module)
#define SPI3MODE1 0<<11 // Data mode: (0,0) transmits 8-bits
#define SPI3MODE0 0<<10 //
#define SPI3SMP 1<<9 // Sampling phase: samples at the end of output data time
#define SPI3CKE 0<<8 // Transmits on transition from idle to active
#define SPI3SSEN 0<<7 // only used in slave mode
#define SPI3CKP 0<<6 // clock idle state is low, active state is high
#define SPI3MSTEN 1<<5 // Master mode enabled
#define SPI3DISSDI 0<<4 // Disable SDI (no data received the board))
#define SPI3DISSCK 0<<3
#define SPI3MCLKEN 1<<2
#define SPI3SPIFE 0<<1
#define SPI3ENHBUF 0<<0
#define SPI3CON1L_MASK (SPI3EN | SPI3SIDL | SPI3DSSDO | SPI3MODE1 | SPI3MODE0 | SPI3SMP |\
SPI3CKE | SPI3SSEN | SPI3CKP | SPI3MSTEN | SPI3DISSDI | SPI3DISSCK | SPI3MCLKEN |\
SPI3SPIFE | SPI3ENHBUF )
// SPI3CON1H
#define AUDEN3 0<<15 // Audio codec enable
#define SPI3SGNEXT 0<<14 // Sign Extend Enable
#define IGNROV3 0<<13 // Ignore Receive Overflow
#define IGNTUR3 0<<12 // Ignore Transmit Underrun
#define AUDMONO3 0<<11 // Audio data format
#define URDTEN3 0<<10 // Transmit underrun data enable
#define AUDMOD31 0<<9 // Audio protocol mode select
#define AUDMOD30 0<<8 //
#define FRMEN3 1<<7 // Framed SPI support
#define FRMSYNC3 0<<6 // Frame sync pulse direction control
#define FRMPOL3 0<<5 // Frame sync/slave select polarity bit
#define MSSEN3 0<<4 // Master mode slave select enable
#define FRMSYPW3 0<<3 // Frame sync pulse width bit
#define FRMCNT32 0<<2 // Frame sync pulse counter bits
#define FRMCNT31 0<<1 //
#define FRMCNT30 0<<0 //
#define SPI3CON1H_MASK (AUDEN3 | SPI3SGNEXT | IGNROV3 | IGNTUR3 | AUDMONO3 | URDTEN3 | AUDMOD31 |\
AUDMOD30 | FRMEN3 | FRMSYNC3 | FRMPOL3 | MSSEN3 | FRMSYPW3 | FRMCNT32 |\
FRMCNT31 | FRMCNT30 )
The function that configures the SPI is found elsewhere:
void SPI3Init(void)
// SPI 3 is the thermocouple interface chip or
// the external adc interface for the cryostat
// **************************************
{
#if PROCESSOR == __PIC24FJ512GA610__
// Used for SPI communication to read RTDs through ADC
IEC3bits.SPI3RXIE = 0; // disable all SPI3 interrupts
IEC5bits.SPI3TXIE = 0;
IEC5bits.SPI3IE = 0;
SPI3BUFL = 0; // clear buffer
SPI3BUFH = 0;
OSCCONbits.IOLOCK = 0;
RPINR28bits.SDI3R = 30; // assign SPI3 SDI to pin 52 (RP30)
// RPINR28bits.SCK3R = 15; // assign SPI3 SCK to pin 53 (RP15)
RPOR7bits.RP15R = 24; // Set SCK pin to SPI3 SCK OUT (function 24)
RPOR8bits.RP16R = 23; // Map SDO to N/C pin 51 (function 23)
OSCCONbits.IOLOCK = 1;
SPI3CON1Lbits.SPIEN = 0; // disable the port
SPI3IMSKH = 0; // disable all interrupts
SPI3CON1L = 0; // disable SPI
SPI3CON1H = 0; // turn off AUDEN & FRMEN
SPI3BRGL = 832; // 3=16mhz / (2* (3+1)) = 2mhz, 7=16/2(7+1) = 1mhz, 832 -> 9600 )
SPI3CON1L = SPI3CON1L_MASK; // Write config masks
SPI3CON1H = SPI3CON1H_MASK;
SPI3CON2L = 7; // 8 bit data
SPI3STATLbits.SPIROV = 0; // clear any overflow status
SPI3CON1Lbits.SPIEN = 1; // enable the port
SPI3BUFL = 0;
ADC_CS_HIGH;
ADC_CS_LOW;
ADC_CS_HIGH;
#endif
return;
}
Actually reading the ADC calls this function three times (one for each 8 bits of resolution)
unsigned char Read_SPI3()
{
unsigned char ioByte = 0;
if(SPI3STATLbits.SPIROV)
SPI3STATLbits.SPIROV = 0; // clear overflow
SPI3BUFL = ioByte; // CLK out data on falling edge
while(!SPI3STATLbits.SPIRBF)
;
ioByte = SPI3BUFL; // CLK in data on rising edge
return ioByte;
}
I have been going through my code for the last day or two and, after combing the internet, cannot figure out what I am doing wrong. Putting a scope on the SCK line indicates that the serial clock is not running. I have confirmed that the config bits are being successfully written. Can anybody tell me what might be wrong?
A few thoughts:
Your setting for DISSDI is enabling SDI (comment says disable)
TRIS register settings are not given, but the pin for SDI must be 1, and the pin for SCLK must be set to 0
by setting MCKLEN, your clock source is REFO - assume it is configured correctly? (e.g. ROEN=1)
With this:
RPOR7bits.RP15R = 24;
you are mapping your SCLK pin to RF8. But you had to switch this pin to an output with.
TRISFbits.TRISF8 = 0;
And you had to switch this pin to digital with
ANSELFbits.ANSELF8 = 0;
Same thing for the SDO pin.
And as #Dan already mentiones, you need a unlock/lock sequence for the PPS. Have aloo at page 163 in the datasheet
The statement you use to unlock the pin selector:
OSCCONbits.IOLOCK = 0;
Is not what Microchip requires.
Because all of the writable bits in the OSCCON register are "protected" a built in compiler extension command must be used to change them.
The command to unlock the PPS looks like this:
__builtin_write_OSCCONL(OSCCON & _OSCCON_IOLOCK_MASK);
The command to lock the PPS looks like this:
__builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK);
Depending on how you have set the configuration words the PPS may be configured so it cannot be unlocked, and once locked it takes a power-on-reset for the PPS to become unlocked.
On a Tiva (Texas Instruments Cortex M4F ARM) TM4C129XNCZAD I have a problem with I2C interface. I have enabled both a master on I2C module 4 thru port K and a slave on I2C module 6 thru port B. I have interconnected both I2C modules. Using Texas Instruments driver library I tried to send 1 byte using I2C_MASTER_CMD_SINGLE_SEND command. I spend a lot of time to make it working, but SCK line keeps Low logical level. I followed exactly TivaWare™ Peripheral Driver Library USER’S GUIDE, but the communication doesn't work. Has anybody some experience with it?
There is my code:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"
#define SLAVE_ADDRESS 0x3C
void delay (void)
{
volatile uint32_t ui32Loop;
for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++);
}
volatile uint32_t result;
int main (void)
{
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
//
// Enable the GPIO port that is used for the on-board LED.
//
SYSCTL_RCGCGPIO_R = SYSCTL_RCGCGPIO_R3 | SYSCTL_RCGCGPIO_R9 | SYSCTL_RCGCGPIO_R1;
//
// Do a dummy read to insert a few cycles after enabling the peripheral.
//
result = SYSCTL_RCGCGPIO_R;
//
// Enable the GPIO pin for the LED (PD3). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIO_PORTD_AHB_DIR_R = 0x8;
GPIO_PORTD_AHB_DEN_R = 0x8;
GPIO_PORTK_DEN_R = 0xC0; // Enable Port K for I2C module 4
GPIO_PORTB_AHB_DEN_R = 0xC0; // Enable Port B for I2C module 6
SYSCTL_RCGCI2C_R = (1 << 4) | (1 << 6); // Mode Clock Gating Control for I2C modules 4 and 6
GPIO_PORTK_AFSEL_R = 0xC0; // Alternate Function Select PK6, PK7
GPIO_PORTB_AHB_AFSEL_R = 0xC0; // Alternate Function Select PB6, PB7
GPIOPinConfigure(GPIO_PK6_I2C4SCL);
GPIOPinConfigure(GPIO_PK7_I2C4SDA);
GPIOPinConfigure(GPIO_PB6_I2C6SCL);
GPIOPinConfigure(GPIO_PB7_I2C6SDA);
GPIOPinTypeI2C(GPIO_PORTK_BASE, 7); // Configurtes SDA
GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, 6); // Configurtes SCL
GPIOPinTypeI2C(GPIO_PORTB_BASE, 7); // Configurtes SDA
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, 6); // Configurtes SCL
I2CMasterInitExpClk(I2C4_BASE, SysCtlClockGet(), false);
I2CSlaveEnable(I2C6_BASE);
I2CSlaveInit(I2C6_BASE, SLAVE_ADDRESS);
I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, false);
//
// Loop forever.
//
while(1)
{
//
// Turn on the LED.
//
GPIO_PORTD_AHB_DATA_R |= 0x8;
I2CMasterDataPut(I2C4_BASE, 0x33);
I2CMasterControl(I2C4_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//
// Wait until the slave has received and acknowledged the data.
//
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
//
// Read the data from the slave.
//
result = I2CSlaveDataGet(I2C6_BASE);
//
// Wait until master module is done transferring.
//
while(I2CMasterBusy(I2C4_BASE));
//
// Delay for a bit.
//
delay ();
//
// Turn off the LED.
//
GPIO_PORTD_AHB_DATA_R &= ~(0x8);
//
// Delay for a bit.
//
delay ();
}
}
The problem has been resolved. There were issues:
It is essential to populate external pull ups.
Use GPIOPinTypeI2C() 2nd parameter as a bit field instead of a bit number.
The procedure SysCtlClockSet() is dedicated specially to TM4C123 devices. Instead use g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 40000000);
For a Master clock setting do not use SysCtlClockGet() procedure. This is also dedicated to TM4C123 devices. Instead use I2CMasterInitExpClk(I2C4_BASE, g_ui32SysClock, false);
Here is the updated code,
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"
#define SLAVE_ADDRESS 0x3C
void delay (void)
{
volatile uint32_t ui32Loop;
for(ui32Loop = 0; ui32Loop < 200; ui32Loop++);
}
volatile uint32_t result;
uint32_t g_ui32SysClock;
int main(void)
{
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 40000000);
//
// Enable the GPIO port that is used for the on-board LED.
//
SYSCTL_RCGCGPIO_R = SYSCTL_RCGCGPIO_R3 | SYSCTL_RCGCGPIO_R9 | SYSCTL_RCGCGPIO_R1;
//
// Do a dummy read to insert a few cycles after enabling the peripheral.
//
result = SYSCTL_RCGCGPIO_R;
//
// Enable the GPIO pin for the LED (PD3). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIO_PORTD_AHB_DIR_R = 0x8;
GPIO_PORTD_AHB_DEN_R = 0x8;
SYSCTL_RCGCI2C_R = (1 << 4) | (1 << 6); // Mode Clock Gating Control for I2C modules 4 and 6
GPIOPinConfigure(GPIO_PK6_I2C4SCL);
GPIOPinConfigure(GPIO_PK7_I2C4SDA);
GPIOPinConfigure(GPIO_PB6_I2C6SCL);
GPIOPinConfigure(GPIO_PB7_I2C6SDA);
GPIOPinTypeI2C(GPIO_PORTK_BASE, (1 << 7)); // Configures SDA
GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, (1 << 6)); // Configures SCL
GPIOPinTypeI2C(GPIO_PORTB_BASE, (1 << 7)); // Configures SDA
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, (1 << 6)); // Configures SCL
I2CMasterInitExpClk(I2C4_BASE, g_ui32SysClock, false);
I2CSlaveEnable(I2C6_BASE);
I2CSlaveInit(I2C6_BASE, SLAVE_ADDRESS);
I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, false);
//
// Loop forever.
//
while(1)
{
//
// Turn on the LED.
//
GPIO_PORTD_AHB_DATA_R |= 0x8;
I2CMasterDataPut(I2C4_BASE, 0x33);
I2CMasterControl(I2C4_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//
// Wait until the slave has received and acknowledged the data.
//
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
//
// Read the data from the slave.
//
result = I2CSlaveDataGet(I2C6_BASE);
//
// Wait until master module is done transferring.
//
while(I2CMasterBusy(I2C4_BASE));
//
// Delay for a bit.
//
delay ();
//
// Turn off the LED.
//
GPIO_PORTD_AHB_DATA_R &= ~(0x8);
//
// Delay for a bit.
//
delay ();
}
}
I was able to get I2C working on TIVA Launchpad TM4C123GH6PM. I used the the Tivaware library. I created 3 functions, init and write. Here are the functions.
Initialization
void initI2C0(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
//reset I2C module
SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
//enable GPIO peripheral that contains I2C
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
// Configure the pin muxing for I2C0 functions on port B2 and B3.
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
// Select the I2C function for these pins.
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
// Enable and initialize the I2C0 master module. Use the system clock for
// the I2C0 module. The last parameter sets the I2C data transfer rate.
// If false the data rate is set to 100kbps and if true the data rate will
// be set to 400kbps.
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
//clear I2C FIFOs
HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;
}
I2C Write Function
void writeI2C0(uint16_t device_address, uint16_t device_register, uint8_t device_data)
{
//specify that we want to communicate to device address with an intended write to bus
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
//register to be read
I2CMasterDataPut(I2C0_BASE, device_register);
//send control byte and register address byte to slave device
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C0_BASE));
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
//specify data to be written to the above mentioned device_register
I2CMasterDataPut(I2C0_BASE, device_data);
//wait while checking for MCU to complete the transaction
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU & device to complete transaction
while(I2CMasterBusy(I2C0_BASE));
}
Complete code for TIVA + I2C can be found here.
Reference
I2C Communication with the TI Tiva TM4C123GXL
I am using a sensor and reading values from it. I have added uart_lite in the xilinx EDK and mapped it's pins to the boards GPIO. The PS (Zynq PS) clock is 50Mhz/100Mhz/200Mhz.
I am receiving data from the RX of UART at 115200 baud rate with 2 stop bits and even parity.
I am using the UART using the registers provided in the document. Four registers are there: ctrl_reg, stat_reg, RX_reg, TX_reg. Using these I can configure my uart to receive data and transmit data. Here is the documentation for uartlite.
Now I am receiving data in and trying to print the data on Teraterm.
Here is the code to set up the uart in correct mode and its registers.
#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"
#define UART_BASE XPAR_AXI_UARTLITE_0_BASEADDR
#define RX_FIFO_REG UART_BASE + 0x00
#define TX_FIFO_REG UART_BASE + 0x04
#define STAT_REG UART_BASE + 0x08
#define CTRL_REG UART_BASE + 0x0C
// Control Register
#define ENA_INTR 27
#define RST_RXFIFO 30
#define RST_TXFIFO 31
// Control Register
// xsp module
unsigned int *pAddr;
#define RS_DXEN 0
#define RS_UART_OUI 1
#define RS_HF_OUT 2
#define RS_RXEN_BAR 3
#define RS_TE_485 4
unsigned int Setting;
// xsp module
unsigned int *pData1, *pData2, *pData3, *pData4;
unsigned int RxStat = 0;
unsigned int RxData = 0;
int main()
{
init_platform();
pAddr = XPAR_UART_IP_0_BASEADDR;
// RS485 RX Mode
Setting = ( 0<<RS_TE_485 | 0<<RS_RXEN_BAR | 1<<RS_HF_OUT | 1<<RS_UART_OUI | 0<<RS_DXEN );
// RS485 TX Mode
//Setting = ( 0<<RS_TE_485 | 1<<RS_RXEN_BAR | 1<<RS_HF_OUT | 1<<RS_UART_OUI | 1<<RS_DXEN );
*pAddr = Setting;
// Control Register
pData1 = CTRL_REG;
*pData1 = (1<<ENA_INTR)|(1<RST_RXFIFO)|(1<RST_TXFIFO);
pData2 = RX_FIFO_REG;//FIFO REG;
pData3 = STAT_REG;//STAT_REG;
pData4 = TX_FIFO_REG; // TX_FIFO_REG
while (1) {
xil_printf("success");
xil_printf("0x%X\r\n",*pData2);
}
return 0;
}
So My while loop should continuously run and print values but it stops only after printing 18 bytes??
but My output is like this:
Here is my debug try:
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
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.