/**************************************************************************//**
* @main_series1_PG1_EFR.c
* @brief Demonstrates USART1 as SPI master.
* @version 0.0.2
******************************************************************************
* @section License
* <b>Copyright 2018 Silicon Labs, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* This file is licensed under the Silabs License Agreement. See the file
* "Silabs_License_Agreement.txt" for details. Before using this software for
* any purpose, you must agree to the terms of that agreement.
*
******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "em_ldma.h"
#define TX_WREN_BUFFER_SIZE 1
#define TX_WRSR_BUFFER_SIZE 4
#define TX_RDSR_BUFFER_SIZE 1
#define RX_BUFFER_SIZE 1
uint8_t Tx_WREN[TX_WREN_BUFFER_SIZE] = {0x06};//write enable command
uint8_t Tx_WRSR[TX_WRSR_BUFFER_SIZE] = {0x01,0x2F,0xEF,0xD8}; //write status register
uint8_t Tx_RDSR[TX_RDSR_BUFFER_SIZE] = {0x05}; //read status register
uint32_t TxBufferIndex = 0;
uint32_t RxBuffer;
//uint32_t RxBufferIndex = 0;
volatile uint32_t msTicks; /* counts 1ms timeTicks */
void Delay(uint32_t dlyTicks);
void SysTick_Handler(void)
{
msTicks++; /* increment counter necessary in Delay()*/
}
void Delay(uint32_t dlyTicks)
{
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks) ;
}
int main(void)
{
CHIP_Init();
CMU_ClockEnable(cmuClock_GPIO, true);
CMU_ClockEnable(cmuClock_USART1, true);
CMU_ClockEnable(cmuClock_USART0, true);
// Configure GPIO mode
GPIO_PinModeSet(gpioPortC, 8, gpioModePushPull, 0); // US1_CLK is push pull
GPIO_PinModeSet(gpioPortA, 4, gpioModePushPull, 1); // US1_CS is push pull
GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); // US1_TX (MOSI) is push pull
GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 1); // US1_RX (MISO) is input
// Start with default config, then modify as necessary
USART_InitSync_TypeDef config = USART_INITSYNC_DEFAULT;
config.master = true; // master mode
config.baudrate = 1000000; // CLK freq is 1 MHz
config.autoCsEnable = false; // CS pin controlled by firmware, not hardware
config.clockMode = usartClockMode0; // clock idle low, sample on rising/first edge
config.msbf = true; // send MSB first
config.enable = usartDisable; // Make sure to keep USART disabled until it's all set up
USART_InitSync(USART1, &config);
USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
// set pin modes for UART TX and RX pins
GPIO_PinModeSet(gpioPortA, 1, gpioModeInput, 1);
GPIO_PinModeSet(gpioPortA, 0, gpioModePushPull, 1);
///////////////////////////////////
USART_InitAsync(USART0, &init);
USART0->ROUTELOC0 =(USART_ROUTELOC0_TXLOC_LOC0) | // US1_TX (MOSI) on location 11 = PC6 per datasheet section 6.4 = EXP Header pin 4
(USART_ROUTELOC0_RXLOC_LOC0); // US1_RX (MISO) on location 11 = PC7 per datasheet section 6.4 = EXP Header pin 6
// Set USART pin locations
USART1->ROUTELOC0 = (USART_ROUTELOC0_CLKLOC_LOC11) | // US1_CLK on location 11 = PC8
(USART_ROUTELOC0_CSLOC_LOC11) | // US1_CS Manual
(USART_ROUTELOC0_TXLOC_LOC11) | // US1_TX (MOSI) on location 11 = PC6
(USART_ROUTELOC0_RXLOC_LOC11); // US1_RX (MISO) on location 11 = PC7
// Enable USART pins
USART1->ROUTEPEN = USART_ROUTEPEN_CLKPEN | USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;
// Enable USART1
USART_Enable(USART1, usartEnable);
TxBufferIndex = 0;
while(1)
{
// Write enable command
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_WREN[0]);
GPIO_PinOutSet(gpioPortA,4);
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_WRSR[0]);
USART_Tx(USART1, Tx_WRSR[1]);
USART_Tx(USART1, Tx_WRSR[2]);
USART_Tx(USART1, Tx_WRSR[3]);
GPIO_PinOutSet(gpioPortA,4);
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_RDSR[0]);
RxBuffer = USART_Rx(USART1);
GPIO_PinOutSet(gpioPortA,4);
// USART_Tx(USART0,RxBuffer);
// USART_Tx(USART0, '\n');
}
}
Hi,
The device does exactly what the code says.
It sets CS .... no wait ... then it clears CS.
--> add some delay between set and clear.
mind: it is manually controlled, thus it has nothing to do with SPI clock.
Klaus
USART_Tx(USART1, Tx_WRSR[0]);
USART1->IEN = USART_IEN_TXDATAV;
while( !(USART1->STATUS & (1 << 6)) );
USART1->CMD |= (1 << 10)
USART1->IEN = USART_IEN_TXDATAV;
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_WRSR[0]);
while( !(USART1->STATUS & (1 << 6)) );
USART1->CMD |= (1 << 10)
USART_Tx(USART1, Tx_WRSR[1]);
while( !(USART1->STATUS & (1 << 6)) );
USART1->CMD |= (1 << 10)
USART_Tx(USART1, Tx_WRSR[2]);
while( !(USART1->STATUS & (1 << 6)) );
USART1->CMD |= (1 << 10)
USART_Tx(USART1, Tx_WRSR[3]);
GPIO_PinOutSet(gpioPortA,4);
Looking at your code, you seem to assume that the USART_Tx function will bock until the value exchange has completed. You need to check that this is the case - and if it isn't (in other words that it simply queues up the value in the USART hardware buffer if there is room) then you need to detect when the buffer is empty and raise the \CS\ pin.(That USART seems to have the ability for the hardware to control the \CS\ line while the buffer is not empty. However you then need to make sure that the buffer is empty BEFORE you start queuing up new values to exchange - there is no free lunch!)
Susan
USART1->IEN = USART_IEN_TXDATAV; //enable TXBL interrupt flag
USART1->CMD |= (1 << 10) //To clear junk data from transmit buffer and Tx shift register
GPIO_PinOutClear(gpioPortA,4); //Low CS
USART_Tx(USART1, Tx_WRSR[0]);//transmit first byte of the command
while( !(USART1->STATUS & (1 << 6)) ); //wait TILL TXBL goes high
USART_Tx(USART1, Tx_WRSR[1]);//transmit second byte of the command
while( !(USART1->STATUS & (1 << 6)) ); //wait TILL TXBL goes high
USART_Tx(USART1, Tx_WRSR[2]);//transmit third byte of the command
while( !(USART1->STATUS & (1 << 6)) ); //wait TILL TXBL goes high
USART_Tx(USART1, Tx_WRSR[3]);//transmit 4th byte of the command
while( !(USART1->STATUS & (1 << 6)) ); //wait TILL TXBL goes high
GPIO_PinOutSet(gpioPortA,4); //High CS so signal the end of SPI session
delay(500) //delay half a second so the device will understand that trnasmition is OVER
You urgently need to read documentation.Hello Klauss ,USART_tx is not blocking.There is SPIDRV command which is blocking but it does not work with manual Chip select.
So the alogrithm for block as i think it should be,is as following:
Clearing buffer->transmitting[0]->waiting->trinsmiting[1]->etc..->CS_high with half second delay.
As shown in the code bellow.
is that the blocking mechnism you suggested?
Thanks.
Why don´t you want the automatic CS control? Why the effort for manual control?
Hi,
Clock usually is just (8 times) active when you send a byte. When you don't send a byte, then clk is idle. Independent of CS.
CS timing.
The chip uses a SYNC signal instead of a SPI standard CS signal. It seems it is designed to be compatible with a CS signal.
However, the timing is clearly specified in "7.6 DACx0004 Timing Requirements".
And it also says:
8.4.1.2.1 SYNC Interrupt – Daisy-Chain Mode
For daisy-chain operation, the SYNC line stays low for at least 32 × N SCLK cycles, where N is the number of
DACx0004s in the daisy chain. If SYNC is brought high before a multiple 32 SCLKs, it acts as an interrupt to the
write sequence;
Klaus
/**************************************************************************//**
* @main_series1_PG1_EFR.c
* @brief Demonstrates USART1 as SPI master.
* @version 0.0.2
******************************************************************************
* @section License
* <b>Copyright 2018 Silicon Labs, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* This file is licensed under the Silabs License Agreement. See the file
* "Silabs_License_Agreement.txt" for details. Before using this software for
* any purpose, you must agree to the terms of that agreement.
*
******************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "bsp.h"
#include "bsp_trace.h"
#include "em_emu.h"
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "em_ldma.h"
#define TX_WREN_BUFFER_SIZE 1
#define TX_WRITE_BUFFER_SIZE 6
#define TX_READ_BUFFER_SIZE 5
#define RX_BUFFER_SIZE 1
uint8_t Tx_WREN[TX_WREN_BUFFER_SIZE] = {0x06};//write enable command
uint8_t Tx_PP[TX_WRITE_BUFFER_SIZE] = {0x02,0x00,0x00,0x00,0x00,0xFF}; //write to all zero register the value FF
uint8_t Tx_READ[TX_READ_BUFFER_SIZE] = {0x03,0x00,0x00,0x00,0x00}; //read register
uint32_t TxBufferIndex = 0;
uint32_t RxBuffer;
//uint32_t RxBufferIndex = 0;
volatile uint32_t msTicks; /* counts 1ms timeTicks */
void Delay(uint32_t dlyTicks);
void SysTick_Handler(void)
{
msTicks++; /* increment counter necessary in Delay()*/
}
void Delay(uint32_t dlyTicks)
{
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks) ;
}
int main(void)
{
CHIP_Init();
CMU_ClockEnable(cmuClock_GPIO, true);
CMU_ClockEnable(cmuClock_USART1, true);
CMU_ClockEnable(cmuClock_USART0, true);
// Configure GPIO mode
GPIO_PinModeSet(gpioPortC, 8, gpioModePushPull, 0); // US1_CLK is push pull
GPIO_PinModeSet(gpioPortA, 4, gpioModePushPull, 1); // US1_CS is push pull
GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); // US1_TX (MOSI) is push pull
GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 1); // US1_RX (MISO) is input
// Start with default config, then modify as necessary
USART_InitSync_TypeDef config = USART_INITSYNC_DEFAULT;
config.master = true; // master mode
config.baudrate = 1000000; // CLK freq is 1 MHz
config.autoCsEnable = false; // CS pin controlled by firmware, not hardware
config.clockMode = usartClockMode0; // clock idle low, sample on rising/first edge
config.msbf = true; // send MSB first
config.enable = usartDisable; // Make sure to keep USART disabled until it's all set up
USART_InitSync(USART1, &config);
USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;
// set pin modes for UART TX and RX pins
GPIO_PinModeSet(gpioPortA, 1, gpioModeInput, 1);
GPIO_PinModeSet(gpioPortA, 0, gpioModePushPull, 1);
///////////////////////////////////
USART_InitAsync(USART0, &init);
USART0->ROUTELOC0 =(USART_ROUTELOC0_TXLOC_LOC0) | // US1_TX (MOSI) on location 11 = PC6 per datasheet section 6.4 = EXP Header pin 4
(USART_ROUTELOC0_RXLOC_LOC0); // US1_RX (MISO) on location 11 = PC7 per datasheet section 6.4 = EXP Header pin 6
// Set USART pin locations
USART1->ROUTELOC0 = (USART_ROUTELOC0_CLKLOC_LOC11) | // US1_CLK on location 11 = PC8
(USART_ROUTELOC0_CSLOC_LOC11) | // US1_CS Manual
(USART_ROUTELOC0_TXLOC_LOC11) | // US1_TX (MOSI) on location 11 = PC6
(USART_ROUTELOC0_RXLOC_LOC11); // US1_RX (MISO) on location 11 = PC7
// Enable USART pins
USART1->ROUTEPEN = USART_ROUTEPEN_CLKPEN | USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;
// Enable USART1
USART_Enable(USART1, usartEnable);
TxBufferIndex = 0;
if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) {
while (1) ;
}
USART1->IEN = USART_IEN_TXC; //enable TXC interrupt flag
while(1)
{
Delay(1);
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_WREN[0]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
GPIO_PinOutSet(gpioPortA,4);
Delay(1);
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_PP[0]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_PP[1]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_PP[2]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_PP[3]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_PP[4]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_PP[5]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
GPIO_PinOutSet(gpioPortA,4);
Delay(1);
//Tx_READ
GPIO_PinOutClear(gpioPortA,4);
USART_Tx(USART1, Tx_READ[0]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_READ[1]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_READ[2]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_READ[3]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
USART_Tx(USART1, Tx_READ[4]);
while( !(USART1->STATUS & USART_STATUS_TXC) ); //wait TILL TXC goes high
GPIO_PinOutSet(gpioPortA,4);
}
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?