UART sometimes lost some characters while communicate with all other devices.
I tried communication with arduino, serial monitor(At PC, with serial-usb converter), HM-10 Bluetooth module.
In every case, my stm32f407 misses some characters when receive data.
(I checked it with LCD. I don't send any data with uart.)
For example, when I send send "This is test string" from PC,
The incoming string is like "Ths is tt sring".
There are no bad characters. It only misses some characters.
In handler, I commented USART_Cmd(...), moved USART_ClearITPendingBit(USART3, USART_IT_RXNE); to the bottom, and changed priority to 0,1,2,3.
However, nothing changed.
My clock is 168MHz and uart uses 9600, or 115200 baudrate.
Both have same problem.
Below is my code.
For some reasons, I can't use HAL driver.
void Uart_Init(long uart_baudrate) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* GPIO Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// USART1 Port Configuration (TX - 9, RX - 10)
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Connect USART pins to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = uart_baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
#define UART_BUF_LEN 64
volatile static char uartBuffer[UART_BUF_LEN];
volatile static int uartBufferIn = 0;
volatile static int uartBufferOut = 0;
//Uart rx handler
void USART3_IRQHandler(void){
unsigned int st1;
st1 = __disable_interrupts();
if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET){
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
uartBuffer[uartBufferIn] = USART_ReceiveData(USART3);
uartBufferIn++;
if(uartBufferIn==uartBufferOut)uartBufferOut++;
uartBufferIn&=0x3F;
uartBufferOut&=0x3F;
}
USART_Cmd(USART3, ENABLE);
__restore_interrupts(st1);
}
//Enable uart rx interrupt
void Uart_Start(void){
unsigned int st1;
st1 = __disable_interrupts();
NVIC_InitTypeDef NVIC_InitStructure;
VectorTable->USART3_IRQHANDLER = USART3_IRQHandler;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART3, ENABLE);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
__restore_interrupts(st1);
}
Related
I am trying to enable UART for STM32 Nucleo - F429ZI.
I have gone through user manual and it says by default USART 3 can be configured for virtual com port purpose. Here is my code. I can see that USART 3 has pins D8 and D9. Here is my code. What am I doing wrong here, I don't see prints on my com port.
Data sheet refered - https://www.st.com/resource/en/data_brief/nucleo-f429zi.pdf
https://www.st.com/resource/en/user_manual/dm00244518-stm32-nucleo-144-boards-stmicroelectronics.pdf
//test print msg
char usr_msg[256];
//Ends
void printmsg(char *msg)
{
for(uint32_t i = 0; i < strlen(msg); i++)
{
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) != SET);
USART_SendData(USART3, msg[i]);
}
}
static void prvSetupUart(void)
{
GPIO_InitTypeDef gpio_uart_pins;
USART_InitTypeDef uart3_init;
//GPIO D is connected to AHB1 bus.
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
// Enable the UART 3 peripheral clock -- connected to APB1 bus.
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// zero the local variable
memset(&gpio_uart_pins,0,sizeof(gpio_uart_pins));
memset(&uart3_init,0,sizeof(uart3_init));
// GPIO port D - pin 8 like TX
// GPIO port D - ping 9 like RX
gpio_uart_pins.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
gpio_uart_pins.GPIO_Mode = GPIO_Mode_AF; //AF - Alternate function i.e. TX and RX.
gpio_uart_pins.GPIO_PuPd = GPIO_PuPd_UP; //Pull up so that we see some default voltage.
GPIO_Init(GPIOD, &gpio_uart_pins);
uart3_init.USART_BaudRate = 115200;
uart3_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
uart3_init.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
uart3_init.USART_Parity = USART_Parity_No;
uart3_init.USART_StopBits = USART_StopBits_1;
uart3_init.USART_WordLength = USART_WordLength_8b;
USART_Init(USART3,&uart3_init);
//Enable USART 3 peripheral.
USART_Cmd(USART3, ENABLE);
}
int main(void)
{
//Step number 1 - DeInit the RCC - Reset Control Clock so that we don't use Pre-scaler or PLL.
// Basically, we want to use lower speed.
RCC_DeInit();
// update the System Core Clock
//Step number 2 -- Update the clock to use the default clock.
SystemCoreClockUpdate();
prvSetupUart();
sprintf(usr_msg, "This is Hello World\r\\n");
printmsg(usr_msg);
for(;;);
}
you forgot to set what AF mode to be used (there are possible 16 AF modes for every pin). At the moment AF registers are set to the 0 and it is wrong. You need to make it 7.
How can it be archived using the SPL library (depreciated and not supported anymore) I do not know.
Here is the register version
#define GPIO_AFRL_AFRL0_Msk (GPIO_AFRL_AFRL0_0 | GPIO_AFRL_AFRL0_1 | GPIO_AFRL_AFRL0_2 | GPIO_AFRL_AFRL0_3)
void GPIO_SetAF(GPIO_TypeDef *gpio, unsigned pin, unsigned AF)
{
volatile uint32_t *AFreg = &gpio -> AFR[pin >= 8];
if(AF <= 15)
{
if(pin > 7) pin -= 8;
*AFreg &= ~(GPIO_AFRL_AFRL0_Msk << (4 * pin));
*AFreg |= (AF << (4 * pin));
}
}
I wrote the code for UART communication. TX is working fine, but RX is not working. I have searched a lot but found no solution.
I am transmitting character x to PC with time interval, and I am able see the data. But when transmits data pic is not receiving any thing.
Below are pins used for uart
//PGEC1/AN4/C1IN1+/RPI34/RB2 for receiver
RPINR18bits.U1RXR = 34;
//RP36/RB4 for transmitting data
RPOR1bits.RP36R = 1;
I am able transmit data to pc but PIC doesn't receive any charector from pc.
Thanks in advance
Here is my code.
DSPIC33EP128MC202
/*
* File: newmainXC16.c
* Author:
*
* Created on 27 December, 2017, 4:21 PM
*/
// FICD
#pragma config ICS = PGD3 // ICD Communication Channel Select bits (Communicate on PGEC3 and PGED3)
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)
// FPOR
#pragma config ALTI2C1 = OFF // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25 // Watchdog Window Select bits (WDT Window is 25% of WDT period)
// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)
// FOSC
#pragma config POSCMD = NONE // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = ON // Peripheral pin select configuration (Allow only one reconfiguration)
#pragma config FCKSM = CSDCMD // Clock Switching Mode bits (Both Clock switching and Fail-safe Clock Monitor are disabled)
// FOSCSEL
#pragma config FNOSC = FRCPLL // Oscillator Source Selection (Fast RC Oscillator with divide-by-N with PLL module (FRCPLL) )
#pragma config PWMLOCK = ON // PWM Lock Enable bit (Certain PWM registers may only be written after key sequence)
#pragma config IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)
// FGS
#pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF // General Segment Code-Protect bit (General Segment Code protect is Disabled)
#include "xc.h"
#include <stdint.h>
#include <p33EP128MC202.h>
#define FP 60000000
#define BAUDRATE 115200
#define BRGVAL ((FP/BAUDRATE)/16)-1
#define DELAY_100uS asm volatile ("REPEAT, #5400"); Nop(); // 100uS delay
int main(void)
{
uint8_t c;
int i,j,a,b;
// Configure Oscillator to operate the device at 60Mhz
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// Fosc= 8M*60/(2*2)=120Mhz for 8M input clock == 8*60/4 = 120/2 = 60
CLKDIVbits.PLLPOST=0; // PLLPOST (N1) 0=/2
while(!OSCCONbits.LOCK); // wait for PLL ready
PLLFBD = 58; // M=60
CLKDIVbits.PLLPOST = 0; // N1=2
CLKDIVbits.PLLPRE = 0; // N2=2
OSCTUN = 0; // Tune FRC oscillator, if FRC is used
/*Initialize the Ports */
TRISA = 0x00;
LATA = 0x0000;
PORTA = 0x0000;
ANSELAbits.ANSA1 = 0;
ANSELAbits.ANSA0 = 0;
__builtin_write_OSCCONL(OSCCON & ~(1<<6));
RPINR18bits.U1RXR = 34;
RPOR1bits.RP36R = 1;
__builtin_write_OSCCONL(OSCCON | (1<<6));
U1MODEbits.STSEL = 0;
U1MODEbits.PDSEL = 0;
U1MODEbits.ABAUD = 0;
U1MODEbits.BRGH = 0;
U1BRG = 30;
U1MODEbits.UARTEN = 1;
IEC0bits.U1TXIE = 0;
U1STAbits.UTXEN = 1;
U1STAbits.URXISEL = 0;
DELAY_100uS;
DELAY_100uS;
DELAY_100uS;
U1TXREG = 'X';
char ReceivedChar;
while(1){
//If data is received send data to TX
if(U1STAbits.URXDA == 1) {
ReceivedChar = U1RXREG + 2;
U1TXREG = 10;
U1TXREG = 13;
}
for(i=0;i<1000;i++){
a = a + 1;
for(j=0;j<2000;j++){
b = b + 1;
}
}
//LED Blink code for programme check
if(c == 0){
c = 1;
}else{
c = 0;
}
LATAbits.LATA0 = c;
LATAbits.LATA1 = c;
U1TXREG = 'x';
U1TXREG = 10;
U1TXREG = 13;
}
}
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt( void )
{
IFS0bits.U1TXIF = 0; // Clear TX Interrupt flag
}
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt( void )
{
IFS0bits.U1RXIF = 0; // Clear RX Interrupt flag
//cntr++;
U1TXREG='a';
U1TXREG = 10;
U1TXREG = 13;
}
I looked into the code, It works fine for me.
Please check the connection with your peripherals and their pins. If there is an extra connection to that pin remove it and try it again.
RB2 should be an an Input.
TRISB = 0x04;
I'm using an STM32F469 Discovery board and I'm trying to use the CAN features.
I understand that on this board CAN1 cannot be used at the same time as the touchscreen. Therefore I need to use CAN2, but in order to enable CAN2, CAN1 needs to be enabled.
My code for configuration/callback is as follows:
/* CAN1 Values */
#define CAN1_CLK_ENABLE() __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN1_FORCE_RESET() __HAL_RCC_CAN1_FORCE_RESET()
#define CAN1_RELEASE_RESET() __HAL_RCC_CAN1_RELEASE_RESET()
#define CAN1_TX_PIN GPIO_PIN_9
#define CAN1_TX_GPIO_PORT GPIOB
#define CAN1_TX_AF GPIO_AF9_CAN1
#define CAN1_RX_PIN GPIO_PIN_8
#define CAN1_RX_GPIO_PORT GPIOB
#define CAN1_RX_AF GPIO_AF9_CAN1
#define CAN1_RX_IRQn CAN1_RX0_IRQn
#define CAN1_RX_IRQHandler CAN1_RX0_IRQHandler
/* CAN2 Values */
#define CAN2_CLK_ENABLE() __HAL_RCC_CAN2_CLK_ENABLE()
#define CAN2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN2_FORCE_RESET() __HAL_RCC_CAN2_FORCE_RESET()
#define CAN2_RELEASE_RESET() __HAL_RCC_CAN2_RELEASE_RESET()
#define CAN2_TX_PIN GPIO_PIN_13
#define CAN2_TX_GPIO_PORT GPIOB
#define CAN2_TX_AF GPIO_AF9_CAN2
#define CAN2_RX_PIN GPIO_PIN_5
#define CAN2_RX_GPIO_PORT GPIOB
#define CAN2_RX_AF GPIO_AF9_CAN2
#define CAN2_RX_IRQn CAN2_RX0_IRQn
#define CAN2_RX_IRQHandler CAN2_RX0_IRQHandler
CAN_HandleTypeDef CanHandle1;
CAN_HandleTypeDef CanHandle2;
static uint8_t Message_Data[8];
static void CAN1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
CAN_FilterConfTypeDef CAN_FilterInitStructure;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;
/* CAN1 peripheral clock enable */
CAN1_CLK_ENABLE();
CAN1_GPIO_CLK_ENABLE();
/* CAN1 TX GPIO pin configuration */
GPIO_InitStruct.Pin = CAN1_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CAN1_TX_AF;
HAL_GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStruct);
/* CAN1 RX GPIO pin configuration */
GPIO_InitStruct.Pin = CAN1_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CAN1_RX_AF;
HAL_GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStruct);
/* NVIC configuration for CAN1 reception complete interrupt */
HAL_NVIC_SetPriority(CAN1_RX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX_IRQn);
CanHandle1.Instance = CAN1;
CanHandle1.pTxMsg = &TxMessage;
CanHandle1.pRxMsg = &RxMessage;
/* CAN peripheral init */
CanHandle1.Init.TTCM = DISABLE;
CanHandle1.Init.ABOM = DISABLE;
CanHandle1.Init.AWUM = DISABLE;
CanHandle1.Init.NART = DISABLE;
CanHandle1.Init.RFLM = DISABLE;
CanHandle1.Init.TXFP = DISABLE;
CanHandle1.Init.Mode = CAN_MODE_LOOPBACK;
CanHandle1.Init.SJW = CAN_SJW_1TQ;
CanHandle1.Init.BS1 = CAN_BS1_6TQ;
CanHandle1.Init.BS2 = CAN_BS2_8TQ;
CanHandle1.Init.Prescaler = 2;
HAL_CAN_Init(&CanHandle1);
/* CAN filter init */
CAN_FilterInitStructure.FilterNumber = 0;
CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInitStructure.FilterIdHigh = 0x0000;
CAN_FilterInitStructure.FilterIdLow = 0x0000;
CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.FilterFIFOAssignment = 0;
CAN_FilterInitStructure.FilterActivation = ENABLE;
CAN_FilterInitStructure.BankNumber = 0;
HAL_CAN_ConfigFilter(&CanHandle1, &CAN_FilterInitStructure);
/* Configure transmission */
CanHandle1.pTxMsg->StdId = 0x7DF;
CanHandle1.pTxMsg->ExtId = 0x7DF;
CanHandle1.pTxMsg->RTR = CAN_RTR_DATA;
CanHandle1.pTxMsg->IDE = CAN_ID_STD;
CanHandle1.pTxMsg->DLC = 8;
}
static void CAN2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
CAN_FilterConfTypeDef CAN_FilterInitStructure;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;
/* CAN2 peripheral clock enable */
CAN2_CLK_ENABLE();
CAN2_GPIO_CLK_ENABLE();
/* CAN2 TX GPIO pin configuration */
GPIO_InitStruct.Pin = CAN2_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CAN2_TX_AF;
HAL_GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStruct);
/* CAN2 RX GPIO pin configuration */
GPIO_InitStruct.Pin = CAN2_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Alternate = CAN2_RX_AF;
HAL_GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStruct);
/* NVIC configuration for CAN2 reception complete interrupt */
HAL_NVIC_SetPriority(CAN2_RX_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN2_RX_IRQn);
CanHandle2.Instance = CAN2;
CanHandle2.pTxMsg = &TxMessage;
CanHandle2.pRxMsg = &RxMessage;
/* CAN peripheral init */
CanHandle2.Init.TTCM = DISABLE;
CanHandle2.Init.ABOM = DISABLE;
CanHandle2.Init.AWUM = DISABLE;
CanHandle2.Init.NART = DISABLE;
CanHandle2.Init.RFLM = DISABLE;
CanHandle2.Init.TXFP = DISABLE;
CanHandle2.Init.Mode = CAN_MODE_LOOPBACK;
CanHandle2.Init.SJW = CAN_SJW_1TQ;
CanHandle2.Init.BS1 = CAN_BS1_6TQ;
CanHandle2.Init.BS2 = CAN_BS2_8TQ;
CanHandle2.Init.Prescaler = 2;
HAL_CAN_Init(&CanHandle2);
/* CAN filter init */
CAN_FilterInitStructure.FilterNumber = 0; //14 enables CAN1;
CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInitStructure.FilterIdHigh = 0x0000;
CAN_FilterInitStructure.FilterIdLow = 0x0000;
CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.FilterFIFOAssignment = 0;
CAN_FilterInitStructure.FilterActivation = ENABLE;
CAN_FilterInitStructure.BankNumber = 0; // 14 enables CAN1
HAL_CAN_ConfigFilter(&CanHandle2, &CAN_FilterInitStructure);
/* Configure transmission */
CanHandle2.pTxMsg->StdId = 0x7DF;
CanHandle2.pTxMsg->ExtId = 0x7DF;
CanHandle2.pTxMsg->RTR = CAN_RTR_DATA;
CanHandle2.pTxMsg->IDE = CAN_ID_STD;
CanHandle2.pTxMsg->DLC = 8;
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
EwBspYellowLedOn();
Message_Data[0] = CanHandle->pRxMsg->Data[0];
Message_Data[1] = CanHandle->pRxMsg->Data[1];
Message_Data[2] = CanHandle->pRxMsg->Data[2];
Message_Data[3] = CanHandle->pRxMsg->Data[3];
Message_Data[4] = CanHandle->pRxMsg->Data[4];
Message_Data[5] = CanHandle->pRxMsg->Data[5];
Message_Data[6] = CanHandle->pRxMsg->Data[6];
Message_Data[7] = CanHandle->pRxMsg->Data[7];
if (HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
{
EwBspRedLedOn();
}
}
CAN_Transmit_Message(void)
{
CanHandle2.pTxMsg->StdId = 0x7DF;
CanHandle2.pTxMsg->ExtId = 0x7DF;
CanHandle2.pTxMsg->Data[0] = 0x02;
CanHandle2.pTxMsg->Data[1] = 0x01;
CanHandle2.pTxMsg->Data[2] = 0x0D;
CanHandle2.pTxMsg->Data[3] = 0x55;
CanHandle2.pTxMsg->Data[4] = 0x55;
CanHandle2.pTxMsg->Data[5] = 0x55;
CanHandle2.pTxMsg->Data[6] = 0x55;
CanHandle2.pTxMsg->Data[7] = 0x55;
if (HAL_CAN_Transmit(&CanHandle, 10) != HAL_OK)
{
EwBspOrangeLedOn();
}
HAL_Delay(10);
}
I then run the following in my main function to configure the CAN1, CAN2 and the interrupt:
/* Configure interrupt for CAN transmission */
CAN1_Config();
CAN2_Config();
HAL_CAN_Receive_IT(&CanHandle2, CAN_FIFO0);
And then I run the CAN_Transmit_Message().
When doing this I have verified the message successfully transmits (the orange LED does not turn on), the receive interrupt handler is then executed (yellow LED turns on) and the message is successfully received (red LED does not turn on).
However, on the second transmission of a message (another call to CAN_Transmit_Message()), the transmit once again succeeds, but the receive fails (red LED turns on).
I created this code by following the structure in the CAN_Networking example code, but I cannot figure out why it is failing at the HAL_CAN_Receive_IT function on the second message (after the first message is successfully received).
Note: After reading the stm32f4xx_HAL_CAN library file, I noticed there are two types of receive/transmit:
HAL_CAN_Transmit_IT/HAL_CAN_Receive_IT
HAL_CAN_Transmit/HAL_CAN_Receive
It says that 1. is nonblocking - I take it this means that another interrupt can be triggered whilst this transmit/receive is still running?
In my case I want to make sure that I receive the response data after sending the transmit to request it, so should I use function 2.? I.e. I would call HAL_CAN_Transmit with a suitable timeout, and then after it completes call HAL_CAN_Receive, again with a suitable timeout.
Do you call HAL_CAN_Receive_IT each time you get a response?
It's one shot. To keep receiving, call it again in your interrupt handler.
From the Reference Manual:
When a message has been received, it is available to the software in the FIFO output mailbox. Once the software has handled the message (e.g. read it) the software must release the FIFO output mailbox by means of the RFOM bit in the CAN_RFR register to make the next incoming message available.
HAL_CAN_Receive_IT contains lines that enable the interrupts and release the FIFO...
/* Enable interrupts: */
/* - Enable Error warning Interrupt */
/* - Enable Error passive Interrupt */
/* - Enable Bus-off Interrupt */
/* - Enable Last error code Interrupt */
/* - Enable Error Interrupt */
/* - Enable Transmit mailbox empty Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
CAN_IT_EPV |
CAN_IT_BOF |
CAN_IT_LEC |
CAN_IT_ERR |
CAN_IT_TME );
/* Process unlocked */
__HAL_UNLOCK(hcan);
if (FIFONumber == CAN_FIFO0)
{
/* Enable FIFO 0 message pending Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
}
else
{
/* Enable FIFO 1 message pending Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP1);
}
I'm developing a project with dsPIC33EV256GM002 and I want to use its UART.
So I decided to use PIN18 as RX and PIN17 as TX so I programed PPS as follow:
// UART1 RX1 18 RP41 RPINR18 010 1001 (41)
// UART1 TX1 17 RP40 RPOR3.RP40R 000 0001 (1)
RPINR18bits.U1RXR=41;
RPOR3bits.RP40R = 1;
and I put PIN18 (RB 9) as input setting the bit9 of TRISB.
I used an external 8M XTAL and I set M,N1 and N2 parameter as follow:
// Configure Oscillator to operate the device at 80MHz/40MIPs
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// Fosc= 8M*40/(2*2)=80Mhz for 8M input clock
// To be safe, always load divisors before feedback
CLKDIVbits.PLLPOST = 0; // N1=2
CLKDIVbits.PLLPRE = 0; // N2=2
PLLFBD = 38; // M=(40-2), Fcyc = 40MHz for ECAN baud timer
// Disable Watch Dog Timer
RCONbits.SWDTEN = 0;
I want to configure the TX/RX port as 31250,N,8,1 (standard MIDI parameters)
// configure U1MODE
U1MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
//U1MODEbits.notimplemented; // Bit14
U1MODEbits.USIDL = 0; // Bit13 Continue in Idle
U1MODEbits.IREN = 0; // Bit12 No IR translation
U1MODEbits.RTSMD = 0; // Bit11 Simplex Mode
//U1MODEbits.notimplemented; // Bit10
U1MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
U1MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
U1MODEbits.LPBACK = 0; // Bit6 No Loop Back
U1MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
U1MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC)
U1MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U1MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
U1MODEbits.STSEL = 0; // Bit0 One Stop Bit
// U1BRG = (Fcy/(16*BaudRate))-1
// Fcy=40
// U1BRG = (40000000/(16*BaudRate))-1
// U1BRG = (40000000/(16*31250))-1 = 79
U1BRG = 79; // 40Mhz osc, 31250 Baud
// Load all values in for U1STA SFR
U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
U1STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
//U1STAbits.notimplemented = 0; //Bit12
U1STAbits.UTXBRK = 0; //Bit11 Disabled
U1STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
U1STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
U1STAbits.TRMT = 0; //Bit8 *Read Only bit*
U1STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
U1STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
U1STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
U1STAbits.PERR = 0; //Bit3 *Read Only Bit*
U1STAbits.FERR = 0; //Bit2 *Read Only Bit*
U1STAbits.OERR = 0; //Bit1 *Read Only Bit*
U1STAbits.URXDA = 0; //Bit0 *Read Only Bit*
IPC2bits.U1RXIP = 1; // Mid Range Interrupt Priority level, no urgent reason
IPC3bits.U1TXIP = 1; // Mid Range Interrupt Priority level, no urgent reason
IFS0bits.U1TXIF = 0; // Clear the Transmit Interrupt Flag
IEC0bits.U1TXIE = 1; // Enable Transmit Interrupts
IFS0bits.U1RXIF = 0; // Clear the Recieve Interrupt Flag
IEC0bits.U1RXIE = 1; // Enable Recieve Interrupts
U1MODEbits.UARTEN = 1; // And turn the peripheral on
for your reference this is the OSC configuration
_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
// Startup directly into XT + PLL
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystal
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software
_FICD(ICS_PGD1); // PGD3 for external PK3/ICD3/RealIce, use PGD2 for PKOB
_FDEVOPT( PWMLOCK_OFF );
_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
// Startup directly into XT + PLL
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystal
Since I can't detect data from serial RX because I detect a framing error, I would know if the setting that I used are correct.
Have you similar experience ?
I have got the UART TX working on one pic but cannot get the UART RX working on another PIC. My plan is to have the first PIC send data to the second PIC.
My initialisation code for the first PIC TX is,
Code:
void configure_TX_port(){
/*Port configurations*/
OSCCON = 0X68;
//Push button
TRISC3 = 1;
INLVLC3 = 0;
ANSC3 = 0;
//Led output
TRISC2 = 0;
//TX output
TRISA2 = 0;
ANSA2 = 0;
/*PPS setup for RA2*/
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCK = 0;
RA2PPS = 0x14;
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCK = 1;
/*UART configuration*/
TXEN = 1;
SYNC = 0;
SPEN = 1;
TXSTA = (0x4|0x20);
SPBRG = (int)(4000000L/(16UL * 9600) -1);
}
My send data to the tx code is
Code:
void putch(unsigned char byte) {
/* output one byte */
while (!TXIF) /* set when register is empty */
TXREG = byte;
}
My initialisation code for the second PIC RX is,
void configure_RX_port(){
/*Port configurations*/
OSCCON = 0X68;
//Led output
TRISC3 = 0;
//RX input
TRISC5 = 1;
ANSC5 = 0;
/*UART configuration*/
CREN = 1;
SYNC = 0;
SPEN = 1;
TXSTA = (0x4|0x20);
RCSTA = 0x90;
SPBRG = (int)(4000000L/(16UL * 9600) -1);
}
My receive data code is,
unsigned char getch(void) {
/* retrieve one byte */
unsigned char ret;
while (!RCIF) { /* set when register is not empty */
}
ret = RCREG;
return ret;
}
When I debug the code the getch function gets blocked waiting on a character but my other PIC is sending data. On this PIC RC5 is a designated RX pin so I dont think I have to do any pps configuration.
Rahul
TX1STA = 0b00100100; This enablex TX (TXEN=1) and high baud rate (BRGH = 1)
RC1STA = 0b10000000; This enable the serial port (SPEN = 1)
The only important missing part is your Clock setting and the baudrate you want to have.
I saw 4000000 in the formula, means 4MHz, and /9600, so assume 9600BDS).
Result = 0x25.
SPBRGL = 0x25;
SPBRGH = 0;
This way, your TX should work. Your tx function is good.
Be sure to configure RX and TX pins as DIGITAL by disabling ANSELA, ANSELB and ANSELC.
Your PIC also use PPS, so be sure to configure it the right way.
*********EDITED POST, RECEIVE CONDITION************
The only difference here to get a working receiver is to enable the continuous receiver
bit, CREN.
RC1STA = 0b10010000; //Enable serial port(SPEN) and continuous receive(CREN).
Be sure to set RX pin (RC5 in your case) as an INPUT (TRISC5 = 1) so that it can read any entering data. You should also consider doing an interrupt routine instead of polling the receiver flag bit. That way you're sure not to skip any entering data.
By default at reset all pins on PIC16F1704 are set as analog.
So clear coresponding bits of RX and TX pins in registers ANSELA, ANSELB and ANSELC to set tham as digital.
You look to be using asynchronous mode with SYNC = 0, but do not set TXEN = 1.
Setting CREN = 1 only overrides TXEN in synchronous mode. Try setting TXEN = 1.
I added the following line, TXSTA = (0x4|0x20); to the receiver PIC code and it works now. There is no need for
CREN = 1;
SYNC = 0;
SPEN = 1;
as its setting the same bits.