Stm32f407IG SPI communication - spi

#include <stm32f4xx.h>
#include "stm32f4xx_spi.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "config.h"
void init_GPIO()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOI , &GPIO_InitStructure);
}
void SPI1_Configuration_master(void)
{
SPI_InitTypeDef SPI_InitStruct;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(Open_SPI1_SCK_GPIO_CLK | Open_SPI1_MISO_GPIO_CLK | Open_SPI1_MOSI_GPIO_CLK |Open_SPI1_NSS_GPIO_CLK ,ENABLE);
RCC_APB2PeriphClockCmd(Open_RCC_APB2Periph_SPI1,ENABLE);
GPIO_PinAFConfig(Open_SPI1_SCK_GPIO_PORT, Open_SPI1_SCK_SOURCE, Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_MISO_GPIO_PORT, Open_SPI1_MISO_SOURCE, Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_MOSI_GPIO_PORT, Open_SPI1_MOSI_SOURCE, Open_SPI1_MOSI_AF);
GPIO_PinAFConfig(Open_SPI1_NSS_GPIO_PORT, Open_SPI1_NSS_SOURCE, Open_SPI1_NSS_AF);
GPIO_InitStructure.GPIO_Pin = Open_SPI1_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(Open_SPI1_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI1_MISO_PIN;
GPIO_Init(Open_SPI1_MISO_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI1_MOSI_PIN;
GPIO_Init(Open_SPI1_MOSI_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI1_NSS_PIN;
GPIO_Init(Open_SPI1_NSS_GPIO_PORT, &GPIO_InitStructure);
SPI_I2S_DeInit(Open_SPI1);
SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(Open_SPI1, &SPI_InitStruct);
SPI_Cmd(Open_SPI1, ENABLE);
}
void SPI_Configuration2_slave(void)
{
SPI_InitTypeDef SPI_InitStruct;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(Open_SPI2_SCK_GPIO_CLK | Open_SPI2_MISO_GPIO_CLK | Open_SPI2_MOSI_GPIO_CLK| Open_SPI2_NSS_GPIO_CLK,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
GPIO_PinAFConfig(Open_SPI2_SCK_GPIO_PORT, Open_SPI2_SCK_SOURCE, Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MISO_GPIO_PORT, Open_SPI2_MISO_SOURCE, Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MOSI_GPIO_PORT, Open_SPI2_MOSI_SOURCE, Open_SPI2_MOSI_AF);
GPIO_PinAFConfig(Open_SPI2_MOSI_GPIO_PORT, Open_SPI2_NSS_SOURCE, Open_SPI2_MOSI_AF);
GPIO_InitStructure.GPIO_Pin = Open_SPI2_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(Open_SPI2_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI2_MISO_PIN;
GPIO_Init(Open_SPI2_MISO_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI2_MOSI_PIN;
GPIO_Init(Open_SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = Open_SPI2_NSS_PIN;
GPIO_Init(Open_SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);
SPI_I2S_DeInit(Open_SPI2);
SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ;
//SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(Open_SPI2, &SPI_InitStruct);
SPI_Cmd(Open_SPI2, ENABLE);
}
u16 SPI2_Send_byte(u16 data)
{
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI2,data);
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI2);
}
u16 SPI2_Receive_byte(void)
{/*
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI2,0x00);
*/
while(SPI_I2S_GetFlagStatus(Open_SPI2, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI2);
}
u16 SPI_Send_byte(u16 data)
{
GPIO_ResetBits(GPIOI,GPIO_Pin_10);
while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI1,data);
while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_RXNE)==RESET);
GPIO_SetBits(GPIOI,GPIO_Pin_10);
return SPI_I2S_ReceiveData(Open_SPI1);
}
u16 SPI_Receive_byte(u16 data)
{
/*while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open_SPI1,data);
*/
while(SPI_I2S_GetFlagStatus(Open_SPI1, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open_SPI1);
}
int main()
{
char a;
init_GPIO();
SPI_Configuration2_slave();
SPI1_Configuration_master();
GPIO_SetBits(GPIOI,GPIO_Pin_10);
while(1)
{
a =SPI_Send_byte((u16)'a');
a = SPI2_Receive_byte();
}
return 0;
}
I am trying to implement Spi on STM32F407ig
I am currently trying to implement communication between two Spi1 and SPI2 on the same board.
I tried the similar code for communication between boards.
when i loop back mosi and miso of master i get the data transmitted.
but the slave does not receive any thing or it receives zero.
The connections made are right.
also the Macros used like Open_SPI1 are right.
I want to know if my configuration of SPI master and slave is right.
Could someone also elaborate on how the NSS software exactly work.

I had an issue with SPI on STM32F2 series. I had to toggle the NSS line manually and everything worked fine after that. Not sure if F4 has the same problem (maybe it's even by design). Here's my code:
/******************************************************************************/
void SPI_GPIO_init( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure SPI pins SCK and MOSI to be hardware controlled */
GPIO_InitStructure.GPIO_Pin = SPI_PIN_SCK | SPI_PIN_MOSI;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
/* Configure SPI pin MISO to be an input pin since we are master */
GPIO_InitStructure.GPIO_Pin = SPI_PIN_MISO;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
/* Configure SPI pin NSS to be a regular GPIO output. This is due to STM32
* goofy handling of SPI: NSS stays low for the entire duration of SPI being
* enabled instead of being released after outgoing data is completed. This
* is basically a HW bug but it definitely mentiones this in the Ref Manual.
*
* From the reference manual RM0090:
* - NSS output enabled (SSM = 0, SSOE = 1)
* This configuration is used only when the device operates in master mode.
* The NSS signal is driven low when the master starts the communication and
* is kept low until the SPI is disabled.
*
* Instead, we are going to drive this pin manually as CLRC663 chip expects
* */
GPIO_InitStructure.GPIO_Pin = SPI_PIN_NSS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init( SPI_GPIO_PORT, &GPIO_InitStructure );
SPI_NSS_high();
DelayMS(1);
}
/******************************************************************************/
void SPI_NSS_high( void )
{
GPIO_WriteBit( SPI_GPIO_PORT, SPI_PIN_NSS, Bit_SET);
}
/******************************************************************************/
void SPI_NSS_low( void )
{
GPIO_WriteBit( SPI_GPIO_PORT, SPI_PIN_NSS, Bit_RESET);
}
/******************************************************************************/
void SPI_init( void )
{
SPI_I2S_DeInit( SPI1 );
SPI_NSS_high();
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 0;
SPI_Init( SPI1, &SPI_InitStructure );
SPI_Cmd( SPI1, ENABLE );
/* Not using interrupts for SPI communication so don't enable the NVIC and
* the ISR for it.*/
}
/******************************************************************************/
Error SPI_send( uint8_t *snd_buf, uint8_t snd_buf_len )
{
uint8_t snd_indx = 0;
uint8_t spi_retry = 0;
SPI_NSS_low(); /* Assert the NSS pin low to become SPI bus master */
for ( snd_indx = 0; snd_indx < snd_buf_len; snd_indx++ )
{
/* When SPI Tx buffer is empty, send data. Make sure we don't get
* stuck in an inf loop while waiting for HW */
spi_retry = 0;
while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) )
{
if ( 0xFF == spi_retry++ )
{
err_printf("Reached SPI hardware retries trying to send data over SPI bus\n");
return ( ERR_HW_SPI_TIMEOUT );
}
}
SPI_I2S_SendData( SPI1, snd_buf[ snd_indx ] );
// debug_printf("Sent %02x\n", snd_buf[ snd_indx ]);
/* Get the dummy byte coming back when SPI Rx buffer is empty. Make sure
* we don't get stuck in an inf loop while waiting for HW */
spi_retry = 0;
while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) )
{
if ( 0xFF == spi_retry++ )
{
err_printf("Reached SPI hardware retries trying to receive data over SPI bus\n");
return ( ERR_HW_SPI_TIMEOUT );
}
}
SPI_I2S_ReceiveData( SPI1 ); /* Dummy byte so no need to store it */
}
SPI_NSS_high(); /* Assert the NSS pin high to release SPI bus master */
return ( ERR_NONE );
}
/******************************************************************************/
Error SPI_transceive(
uint8_t *snd_buf,
uint8_t snd_buf_len,
uint8_t *rcv_buf,
uint8_t rcv_buf_len
)
{
uint8_t snd_indx = 0;
uint8_t rcv_indx = 0;
uint16_t spi_retry = 0;
SPI_NSS_low(); /* Assert the NSS pin low to become SPI bus master */
if ( snd_buf_len != rcv_buf_len )
{
err_printf("SPI expects to receive same amount of data that it is sending\n");
return ( ERR_HW_SPI_LENGTH_MISMATCH );
}
for ( snd_indx = 0; snd_indx < snd_buf_len; snd_indx++, rcv_indx++ )
{
/* When SPI Tx buffer is empty, send data. Make sure we don't get
* stuck in an inf loop while waiting for HW */
spi_retry = 0;
while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) )
{
if ( 0xFF == spi_retry++ )
{
err_printf("Reached SPI hardware retries trying to send data over SPI bus\n");
return ( ERR_HW_SPI_TIMEOUT );
}
}
SPI_I2S_SendData( SPI1, snd_buf[ snd_indx ] );
/* Now receive the reply when the Rx buffer is empty. Make sure we don't
* get stuck in an inf loop while waiting for HW */
spi_retry = 0;
while ( SET != SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) )
{
if ( 0xFF == spi_retry++ )
{
err_printf("Reached SPI hardware retries trying to receive data over SPI bus\n");
return ( ERR_HW_SPI_TIMEOUT );
}
}
uint8_t data = SPI_I2S_ReceiveData( SPI1 );
rcv_buf[ rcv_indx ] = data;
// debug_printf("Got %02x\n", data );
}
SPI_NSS_high(); /* Assert the NSS pin high to release SPI bus master */
return ( ERR_NONE );
}

Related

why this code using dspic33ep512mu810 chip uart 2 not working

In MPLAB X IDE v5.10, I am using dspic33ep512mu810 microcontroller.
I have following piece of C code:
#include "xc.h"
_FOSCSEL(FNOSC_FRCPLL) //INT OSC with PLL (always keep this setting)
_FOSC(OSCIOFNC_OFF & POSCMD_NONE) //disable external OSC
_FWDT(FWDTEN_OFF) //watchdog timer off
_FICD(JTAGEN_OFF & 0b11); //JTAG debugging off
void UART2TX(char c) {
if (U2STAbits.UTXEN == 0)
U2STAbits.UTXEN = 1; //enable UART TX
while (U2STAbits.UTXBF == 1); //if buffer is full, wait
U2TXREG = c;
}
int main(void) {
//setup internal clock for 80MHz/40MIPS
//7.37/2=3.685*43=158.455/2=79.2275
CLKDIVbits.PLLPRE = 0; // PLLPRE (N2) 0=/2
PLLFBD = 41; //pll multiplier (M) = +2
CLKDIVbits.PLLPOST = 0; // PLLPOST (N1) 0=/2
while (!OSCCONbits.LOCK); //wait for PLL ready
_U2TXIF = 0;
_U2TXIE = 0;
_U2RXIF = 0;
_U2RXIE = 0;
//setup UART
U2BRG = 85; //86#80mhz, 85#79.xxx=115200
U2MODE = 0; //clear mode register
U2MODEbits.BRGH = 1; //use high percison baud generator
U2STA = 0; //clear status register
//DSPIC33EP512MU810T-I/PT, RP96 as TX pin
RPOR7bits.RP96R = 3; //
while (1) {
UART2TX('H');
}
}
I am trying to send out 'H' through UART2 with baud rate 115200, but it is not working.
You had to switch RF0 (RP96) aus output:
TRISFbits.TRISF0 = 0; //make F0 an onput
And you had to switch RFO to digital:
ANSELFbits.ANSF0 = 0; //make F0 digital

STM32 HAL_UART_Transmit_IT never returns

I have created a project using cube mx and want to use the uart4 tx and rx to send and receive bytes in interrupt mode.
I have :
uint8_t buffer[] = "test\r\n";
if(HAL_UART_Transmit_IT(&huart4, (uint8_t*)buffer, strlen(buffer))!= HAL_OK)
{
}
The uart initialisation is
static void MX_UART4_Init(void)
{
huart4.Instance = UART4;
huart4.Init.BaudRate = 9600;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
The call to Transmit never returns and just sits there.
In the msp file I have
HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
and have in the it file
void UART4_IRQHandler(void)
{
/* USER CODE BEGIN UART4_IRQn 0 */
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
/* USER CODE END UART4_IRQn 1 */
}
what am I missing?
the problem is related to uint8_t buffer[] = "test\r\n";
the right side is char and the left side is uint8. So, you must do as follows
char buffer[] = "test\r\n";
if(HAL_UART_Transmit_IT(&huart4, (char*)buffer, strlen(buffer))!= HAL_OK)
{
}
or you can do this (use sizeof for int8_t not strlen)
unit8_t buffer[] = "test\r\n";
if(HAL_UART_Transmit_IT(&huart4, (uint8_t*)buffer, sizeof(buffer))!= HAL_OK)
{
}
please add "string.h" and in the first line of you code
Adding a delay too allow the data to be sent fixed this problem. HAL_Delay(100)

STM32F4329II Input capture Interrupt ignored

STM32F4329II Input capture Interrupt is ignored while trying to use the input capture
 
static void TIM_Config(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //GPIO_PuPd_NOPULL;
GPIO_PinAFConfig(GPIOH, GPIO_PinSource11, GPIO_AF_TIM5);
GPIO_Init(GPIOH, &GPIO_InitStructure);
/* TIM5 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_ICInitTypeDef TIM_InputCaptureInitStructure;
TIM_InputCaptureInitStructure.TIM_Channel = TIM_Channel_2;
TIM_InputCaptureInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_InputCaptureInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_InputCaptureInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_InputCaptureInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM5, &TIM_InputCaptureInitStructure);
TIM_ClearFlag(TIM5, TIM_FLAG_CC2 );
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //
NVIC_Init(&NVIC_InitStructure);
TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
//Enable CC2 interrupt
TIM_ITConfig(TIM5,TIM_IT_CC2,ENABLE);
//EnableTIM5
TIM_Cmd(TIM5,ENABLE);
}
And the following IRQ
extern "C" void TIM5_IRQHandler(void)
{
if (TIM_GetITStatus(TIM5, TIM_IT_CC2) == SET)
{
TIM_ClearITPendingBit(TIM5, TIM_IT_CC2);
rpm4 = TIM_GetCapture2(TIM5);
static char xx[12];
sprintf( xx, " %l", rpm4 );
GUI_DispStringAt(xx,100,150);
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC2 );
}
I put some breakpoints inside the Interrupt routine but nothing happens...
My external signal is a 5V signal ( this micro is 5V tolerant... ) with negative pulses...

STM32F3 I2C read data

I'm using the STM32F373 microcontroller and wrote a simple function to read data from a MPU6050 gyro+accel on i2c 1 (PB7 PB6).
The problem is that when I try to read sensor register data - flag I2C_ISR_TXIS is always equal to RESET (not set).
Why might this happen?
Here is some source code that demonstrates the problem.
void i2c1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_4);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_4);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_Timing = 0xC062121F;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
uint8_t i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t* pBuffer, uint16_t len)
{
/* Test on BUSY Flag */
uint32_t timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET)
{
if((timeout--) == 0) return 0;
}
I2C_TransferHandling(I2C1, DeviceAddr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
/* !!! Wait until TXIS flag is set !!! */
timeout = I2C_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET) // PROBLEM HERE!!!!!!!!!!!!!!!
{
if((timeout--) == 0) return 0;
}
....
....
}
OK,I found the problem. Flag I2C_ISR_TXIS did not get because the device on the i2c did not respond to the sent address. Need to convert the device address to 7 bits.
(DeviceAddr & 0x7f) << 1

ARM LPC1768 UART0 configuration, wrong baud rate

My baud rate should be 115200, but it is 892.9
void UART0_Init(int pclk, int baudrate)
{
unsigned long int DLest;
//unsigned long int pclk;
unsigned int temp;
// Turn on power to UART0
SC->PCONP |= PCUART0_POWERON;
// Set PINSEL0 so that P0.2 = TXD0, P0.3 = RXD0
PINCON->PINSEL0 = (PINCON->PINSEL0 & ~0xf0) | (1 << 4) | (1 << 6);
UART0->LCR = 0x83; // 8 bits, no Parity, 1 Stop bit, DLAB=1
DLest = (pclk / 16) / baudrate; // Set baud rate
UART0->DLM = DLest / 256;
UART0->DLL = DLest % 256;
// UART0->FDR =
UART0->IER = 0x7; //enable RBR (b0), THRE(b1), RLS(b2)
UART0->LCR = 0x03; // 8 bits, no Parity, 1 Stop bit DLAB = 0
UART0->FCR = 0x07; // Enable and reset TX and RX FIFO
}
void prvSetupHardware( void )
{
/* Disable peripherals power. */
SC->PCONP = 0;
/* Enable GPIO power. */
SC->PCONP = PCONP_PCGPIO;
/* Disable TPIU. */
PINCON->PINSEL10 = 0;
if ( SC->PLL0STAT & ( 1 << 25 ) )
{
/* Enable PLL, disconnected. */
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
}
/* Disable PLL, disconnected. */
SC->PLL0CON = 0;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Enable main OSC. */
SC->SCS |= 0x20;
while( !( SC->SCS & 0x40 ) );
/* select main OSC, 12MHz, as the PLL clock source. */
SC->CLKSRCSEL = 0x1;
SC->PCLKSEL0 = 0xAAAAAAAA; /* PCLK is 1/2 CCLK */
SC->PCLKSEL1 = 0xAAAAAAAA;
/*Fcc0 = 400MHz, M = 50, N = 3*/
SC->PLL0CFG = 0x20031;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Enable PLL, disconnected. */
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Set clock divider. */
/*Clock = 100MHz, Fcc0 = 400MHz*/
SC->CCLKCFG = 0x03;//divided by 4.
/* Configure flash accelerator. */
SC->FLASHCFG = 0x403a;
/* Check lock bit status. */
while( ( ( SC->PLL0STAT & ( 1 << 26 ) ) == 0 ) );
/* Enable and connect. */
SC->PLL0CON = 3;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
while( ( ( SC->PLL0STAT & ( 1 << 25 ) ) == 0 ) );
/* Configure the clock for the USB. */
if( SC->PLL1STAT & ( 1 << 9 ) )
{
/* Enable PLL, disconnected. */
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
}
/* Disable PLL, disconnected. */
SC->PLL1CON = 0;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
SC->PLL1CFG = 0x23;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
/* Enable PLL, disconnected. */
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
while( ( ( SC->PLL1STAT & ( 1 << 10 ) ) == 0 ) );
/* Enable and connect. */
SC->PLL1CON = 3;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
while( ( ( SC->PLL1STAT & ( 1 << 9 ) ) == 0 ) );
/* Configure the LEDs. */
vParTestInitialise();
/*pclk = 100MHZ/2, baud = 115200 */
UART0_Init(100000000/2, 115200);
/* Set the sleep mode to highest level sleep*/
SC->PCON = 0x0;
SCB->SCR = 0x0;
/*set push button interrupt */
PINCON->PINSEL4 |= 0x00100000;
SC->EXTMODE =0;
NVIC_SetPriority( EINT0_IRQn, configUIButton1_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( EINT0_IRQn );
NVIC_SetPriority( UART0_IRQn, configUIButton1_INTERRUPT_PRIORITY + 1 );
NVIC_EnableIRQ( UART0_IRQn );
}
I have confirmed that my cclk is running at 100MHz.
I replace the UART init code with code from an example project by Kunil (uart_interrupt_demo):
void uart_init(int baudrate) {
int errorStatus = -1; //< Failure
long int SystemFrequency = 100000000;
// UART clock (FCCO / PCLK_UART0)
unsigned int uClk = SystemFrequency / 4;
unsigned int calcBaudrate = 0;
unsigned int temp = 0;
unsigned int mulFracDiv, dividerAddFracDiv;
unsigned int divider = 0;
unsigned int mulFracDivOptimal = 1;
unsigned int dividerAddOptimal = 0;
unsigned int dividerOptimal = 0;
unsigned int relativeError = 0;
unsigned int relativeOptimalError = 100000;
// Turn on power to UART0
SC->PCONP |= PCUART0_POWERON;
// Change P0.2 and P0.3 mode to TXD0 and RXD0
PINCON->PINSEL0 = (1 << 4) | (1 << 6);
// Set 8N1 mode
UART0->LCR = 0x83;
// Set the baud rate
uClk = uClk >> 4; /* div by 16 */
/*
* The formula is :
* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * DLL)
*/
/*
* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15
*/
for (mulFracDiv = 1; mulFracDiv <= 15; mulFracDiv++) {
for (dividerAddFracDiv = 0; dividerAddFracDiv <= 15; dividerAddFracDiv++) {
temp = (mulFracDiv * uClk) / (mulFracDiv + dividerAddFracDiv);
divider = temp / baudrate;
if ((temp % baudrate) > (baudrate / 2))
divider++;
if (divider > 2 && divider < 65536) {
calcBaudrate = temp / divider;
if (calcBaudrate <= baudrate) {
relativeError = baudrate - calcBaudrate;
} else {
relativeError = calcBaudrate - baudrate;
}
if (relativeError < relativeOptimalError) {
mulFracDivOptimal = mulFracDiv;
dividerAddOptimal = dividerAddFracDiv;
dividerOptimal = divider;
relativeOptimalError = relativeError;
if (relativeError == 0)
break;
}
}
}
if (relativeError == 0)
break;
}
if (relativeOptimalError
< ((baudrate * UART_ACCEPTED_BAUDRATE_ERROR) / 100)) {
UART0->LCR |= DLAB_ENABLE;
UART0->DLM = (unsigned char) ((dividerOptimal >> 8) & 0xFF);
UART0->DLL = (unsigned char) dividerOptimal;
UART0->LCR &= ~DLAB_ENABLE;
UART0->FDR = ((mulFracDivOptimal << 4) & 0xF0) | (dividerAddOptimal
& 0x0F);
errorStatus = 0; //< Success
}
// Enable TX and RX FIFO
UART0->FCR |= FIFO_ENABLE;
// Set FIFO to trigger when at least 14 characters available
UART0->FCR |= (3 << 6);
// Enable UART RX interrupt (for LPC17xx UART)
UART0->IER = RBR_IRQ_ENABLE;
// Enable the UART interrupt (for Cortex-CM3 NVIC)
NVIC_EnableIRQ(UART0_IRQn);
}
And it works!
I have to go through and see what i had wrong. I suspect the order of register settings was off.
Have a look at the Errata sheet.
You can't set SC->PCLKSEL0 after you fired up the main PLL, so the divider stays at CCLK/4.
Just move the line
/* Setup the peripheral bus to be the same as the PLL output (64 MHz). */
SC->PCLKSEL0 = 0x05555555;
a few lines up, before you enable the PLL.
Suspect that clk for UART is further divided from the cclk. You need to check the datasheet and update accordingly.
I wanted a simplified driver for my LPC1768 UART1 port so I have written a baud rate calculator application based on CMSIS code.
You provide the Peripheral Clock Frequency and Desired Baud Rate and it will generate the DLL, Fractional Multiplier & Divider and finally recalculates with the computed values to indicate the Baud rate achievable.
I have tested it with a peripheral clock of 25MHz and baud rates of 115200 & 9600 with success. It does not calculate DLM which is generally 0 for bauds above 4800.
It is available at a freeware download site.
http://sabercathost.com/6y6
I have a reputation to maintain and to that end the application I uploaded does not contain a virus.
HTH
Mark
As requested by Drew I've appended the CMSIS function I used in my code below.
/*********************************************************************//**
* #brief Determines best dividers to get a target clock rate
* #param[in] UARTx Pointer to selected UART peripheral, should be:
* - LPC_UART0: UART0 peripheral
* - LPC_UART1: UART1 peripheral
* - LPC_UART2: UART2 peripheral
* - LPC_UART3: UART3 peripheral
* #param[in] baudrate Desired UART baud rate.
* #return Error status, could be:
* - SUCCESS
* - ERROR
**********************************************************************/
static Status uart_set_divisors(LPC_UART_TypeDef *UARTx, uint32_t baudrate)
{
Status errorStatus = ERROR;
uint32_t uClk;
uint32_t d, m, bestd, bestm, tmp;
uint64_t best_divisor, divisor;
uint32_t current_error, best_error;
uint32_t recalcbaud;
/* get UART block clock */
if (UARTx == LPC_UART0)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART0);
}
else if (UARTx == (LPC_UART_TypeDef *)LPC_UART1)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART1);
}
else if (UARTx == LPC_UART2)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART2);
}
else if (UARTx == LPC_UART3)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART3);
}
/* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
* The formula is :
* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
* It involves floating point calculations. That's the reason the formulae are adjusted with
* Multiply and divide method.*/
/* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
best_error = 0xFFFFFFFF; /* Worst case */
bestd = 0;
bestm = 0;
best_divisor = 0;
for (m = 1 ; m <= 15 ;m++)
{
for (d = 0 ; d < m ; d++)
{
divisor = ((uint64_t)uClk<<28)*m/(baudrate*(m+d));
current_error = divisor & 0xFFFFFFFF;
tmp = divisor>>32;
/* Adjust error */
if(current_error > ((uint32_t)1<<31)){
current_error = -current_error;
tmp++;
}
if(tmp<1 || tmp>65536) /* Out of range */
continue;
if( current_error < best_error){
best_error = current_error;
best_divisor = tmp;
bestd = d;
bestm = m;
if(best_error == 0) break;
}
} /* end of inner for loop */
if (best_error == 0)
break;
} /* end of outer for loop */
if(best_divisor == 0) return ERROR; /* can not find best match */
recalcbaud = (uClk>>4) * bestm/(best_divisor * (bestm + bestd));
/* reuse best_error to evaluate baud error*/
if(baudrate>recalcbaud) best_error = baudrate - recalcbaud;
else best_error = recalcbaud -baudrate;
best_error = best_error * 100 / baudrate;
if (best_error < UART_ACCEPTED_BAUDRATE_ERROR)
{
if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
{
((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_DLAB_EN;
((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
/* Then reset DLAB bit */
((LPC_UART1_TypeDef *)UARTx)->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
((LPC_UART1_TypeDef *)UARTx)->FDR = (UART_FDR_MULVAL(bestm) \
| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
}
else
{
UARTx->LCR |= UART_LCR_DLAB_EN;
UARTx->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
UARTx->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
/* Then reset DLAB bit */
UARTx->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
UARTx->FDR = (UART_FDR_MULVAL(bestm) \
| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
}
errorStatus = SUCCESS;
}
return errorStatus;
}