동일한 장비에 동일한 코드인데도, USART3 통신이 되는것이 있고, 안되는것이 있다.
증상) 10바이트 보내면, 9,10,8,,10,10,10바이트등으로 전송된다.
원인1) UART통신과 아무 관련 없는 코드가 통신에 영향을 준다.
해당코드를 제거하니, 정상동작함.(최적화와는 상관없는듯.)
keill은 최적화 안함으로 설정하는 방법이 없는듯 하다. 최적화 정도도 매번 다르다.
원인2) USART3->BRR=50000000/Baud_rate;//434이고, 통신 데이터가 다 깨진다.
통신이 잘안되는 이코드에 USART3->BRR=477을 넣으면 잘된다.
Baud계산이 잘못될 수 있다는 내용의 글들이 인터넷에 있다.
(찾았는데, 잊어버렸다.. 직접 찾아봐라.)
그래서, 이문제를 간단하게 해결할 수 있는 방법으로,
기존코드가 계산한 값 -@ ~ +@까지 직접 통신데이터를 출력해보고,
정상적으로 전송되는 BAUD값을 사용하기로 했다.
BAUD값이 1차이가 난다고, 통신이 아예 안되는건 아니다.
a~b까지는 거의 정상적으로 통신을 할 수 있다.
(a+b)/2값이 가장 통신이 잘되는 값일듯 하나, 직접해보니, 또 그렇지도 않은듯 하다.(통신은 잘 된다)
요약 : Baud값을 변경하면서, 통신이 잘되는 범위 측정하여 평균값 사용.
(stm32 사용하면서 별 드러운 버그 몇개 만나보면, .... 버그 없는 칩은 없겠지만...)
#include <UART.h>
#include "stm32f7xx_hal.h"
#include "..\src\FIFO.h"
#include "..\src\cpu.h"
void UART_ER_Control(USART_TypeDef* Serial_USART)
{
uint32_t ERROR_Code = Serial_USART->ISR;
if((ERROR_Code & USART_ISR_PE)==USART_ISR_PE)
{
Serial_USART->ICR = USART_ICR_PECF;
Serial_USART->CR1 &= ~0x01;
Serial_USART->CR1 |= 0x01;
//NVIC_SystemReset();
}
else if((ERROR_Code & USART_ISR_FE)==USART_ISR_FE)
{
Serial_USART->ICR = USART_ICR_FECF;
Serial_USART->CR1 &= ~0x01;
Serial_USART->CR1 |= 0x01;
//NVIC_SystemReset();
//HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
}
else if((ERROR_Code & USART_ISR_NE)==USART_ISR_NE)
{
Serial_USART->ICR = USART_ICR_NCF;
Serial_USART->CR1 &= ~0x01;
Serial_USART->CR1 |= 0x01;
//NVIC_SystemReset();
//HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
}
else if((ERROR_Code & USART_ISR_ORE)==USART_ISR_ORE)
{
Serial_USART->RQR = USART_RQR_RXFRQ;
Serial_USART->ICR = USART_ICR_ORECF;
Serial_USART->CR1 &= ~0x01;
Serial_USART->CR1 |= 0x01;
//NVIC_SystemReset();
}
}
#ifndef UART3_TX_WAIT
#define UART3_TX_WAIT() while((USART3->ISR & USART_ISR_TXE)==0);
#endif
#define UART1_RX_BUF_SIZE (512)
#define UART1_TX_BUF_SIZE (1024)
#define UART2_RX_BUF_SIZE (512)
#define UART2_TX_BUF_SIZE (1024)
#define UART3_RX_BUF_SIZE (512)
#define UART3_TX_BUF_SIZE (1024)
volatile sFIFO UART1_rx_fifo,UART1_tx_fifo;
byte1 UART1_rx_fifo_buf[UART1_RX_BUF_SIZE],UART1_tx_fifo_buf[UART1_TX_BUF_SIZE];
volatile sFIFO UART2_rx_fifo,UART2_tx_fifo;
byte1 UART2_rx_fifo_buf[UART2_RX_BUF_SIZE],UART2_tx_fifo_buf[UART2_TX_BUF_SIZE];
volatile sFIFO UART3_rx_fifo,UART3_tx_fifo;
byte1 UART3_rx_fifo_buf[UART3_RX_BUF_SIZE],UART3_tx_fifo_buf[UART3_TX_BUF_SIZE];
#define USART3_SET_BRR() USART3->BRR=477
void UART3_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_TypeDef* Serial_USART=USART3;
uint32_t Baud_rate=115200;
sFIFO_init(&UART3_rx_fifo,UART3_rx_fifo_buf,sizeof(UART3_rx_fifo_buf));
sFIFO_init(&UART3_tx_fifo,UART3_tx_fifo_buf,sizeof(UART3_tx_fifo_buf));
//GPIO Ports Clock Enable
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_USART3_CLK_ENABLE();
//UART3
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
//Serial_FPGA default setting
Serial_USART->CR1 = 0x2d; // Interrupt Setting and Usart operation
Serial_USART->CR2 = 0x00;
Serial_USART->CR3 = 0x01;
//Serial_USART->BRR = 50000000/Baud_rate; //434(Clock/BRR)
USART3_SET_BRR();
HAL_NVIC_EnableIRQ(USART3_IRQn);//interrupt 설정
//DEBUG while(1)
USART3->TDR=0;
}
void UART_init(USART_TypeDef* Serial_USART,uint32_t Baud_rate)
{
Serial_USART->CR1 = 0x2d; // Interrupt Setting and Usart operation
Serial_USART->CR2 = 0x00;
Serial_USART->CR3 = 0x01;
if(Serial_USART == USART1)
{
sFIFO_init(&UART1_rx_fifo,UART1_rx_fifo_buf,sizeof(UART1_rx_fifo_buf));
sFIFO_init(&UART1_tx_fifo,UART1_tx_fifo_buf,sizeof(UART1_tx_fifo_buf));
RCC->DCKCFGR2 &=0xFFFFFFFC; //USART1 in sys clock
RCC->DCKCFGR2 |=0x00000001; //USART1 in sys clock
Serial_USART->BRR = 200000000/Baud_rate;
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
else if(Serial_USART == USART2)
{
sFIFO_init(&UART2_rx_fifo,UART2_rx_fifo_buf,sizeof(UART2_rx_fifo_buf));
sFIFO_init(&UART2_tx_fifo,UART2_tx_fifo_buf,sizeof(UART2_tx_fifo_buf));
Serial_USART->BRR = 50000000/Baud_rate; //(Clock/BRR)
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
else if(Serial_USART == USART3)
{
sFIFO_init(&UART3_rx_fifo,UART3_rx_fifo_buf,sizeof(UART3_rx_fifo_buf));
sFIFO_init(&UART3_tx_fifo,UART3_tx_fifo_buf,sizeof(UART3_tx_fifo_buf));
//Serial_USART->BRR = 50000000/Baud_rate; //434 //(Clock/BRR)
USART3_SET_BRR();
HAL_NVIC_EnableIRQ(USART3_IRQn); //interrupt 설정
}
else
{
}
}
void UART3_putch(char a);
void UART1_putch(char a)
{
//UART3_putch(a);
/*USART1->CR1|=USART_CR1_TCIE;
USART1->TDR=a;
while ((USART1->ISR & USART_CR1_TCIE)==0);
USART1->CR1&=~USART_CR1_TCIE;*/
USART1->CR1 &= ~USART_CR1_TCIE;//전송중단
sFIFO_push(&UART1_tx_fifo,a);
USART1->CR1|=USART_CR1_TCIE;
}
void UART3_putch(char a)
{
/*USART3->CR1|=USART_CR1_TCIE;
USART3->TDR=a;
while ((USART3->ISR & USART_CR1_TCIE)==0);
USART3->CR1&=~USART_CR1_TCIE;*/
//USART3->CR1&=~USART_CR1_TCIE;//인터럽트 금지
USART3->CR1 &= ~USART_CR1_TCIE;//전송중단
sFIFO_push(&UART3_tx_fifo,a);
USART3->CR1|=USART_CR1_TCIE;
}
void UART1_write(void *pdata,int len)
{
while(sFIFO_EmptyCount(&UART1_tx_fifo)<len)
{
Sleep(1);
}
USART1->CR1 &= ~USART_CR1_TCIE;//전송중단
sFIFO_write(&UART1_tx_fifo,pdata,len);
USART1->CR1|=USART_CR1_TCIE;
}
void UART3_write(void *pdata,int len)
{
/*byte1 *p=(byte1 *)pdata;
while(len)
{
UART3_putch(*p);
p++;
len--;
}*/
while(sFIFO_EmptyCount(&UART3_tx_fifo)<len)
//while(sFIFO_Count(&UART3_tx_fifo)>0)
{
USART3->CR1|=USART_CR1_TCIE;
Sleep(1);
}
USART3->CR1 &= ~USART_CR1_TCIE;//전송중단
sFIFO_write(&UART3_tx_fifo,pdata,len);
USART3->CR1|=USART_CR1_TCIE;
}
void UART1_tx_end_wait(void)
{
while(UART1_tx_fifo.cnt>0)
{
Sleep(1);
}
}
void UART3_tx_end_wait(void)
{
while(UART3_tx_fifo.cnt>0)
{
Sleep(1);
}
}
#include "string.h"
void UART1_puts(char *s)
{
UART3_write(s,strlen(s));
}
void UART3_puts(char *s)
{
UART3_write(s,strlen(s));
}
void HEX_puts(char *s,void *pdata,int len,void (*xputs)(char *s))
{
int blen;
char buf[16*4];
byte1 *p=(byte1 *)pdata;
xputs(s);
sprintf(buf,",len=%d\r\n",len);
xputs(buf);
while(len>0)
{
if(len>16)
{
blen=16;
}
else
{
blen=len;
}
BinToHEX(p,blen,buf);
xputs(buf);
len-=blen;
p+=blen;
}
xputs("\r\n");
}
void UART3_puts_int(char *s,int a)
{
char buf[256];
sprintf(buf,"%s=%d\r\n",s,a);
UART3_puts(buf);
}
void USART1_IRQHandler(void)
{
byte1 a;
if((USART1->ISR & USART_ISR_RXNE) == USART_ISR_RXNE) // 수신버퍼에 데이터가 들어오면
{
a=USART1->RDR;
//USART1->TDR=a;//DEBUG
//USART3->TDR=a;//DEBUG
sFIFO_push(&UART1_rx_fifo,a);
}
if(USART1->ISR & USART_CR1_TCIE)
{
if(sFIFO_Count(&UART1_tx_fifo)==0)
{
USART1->CR1 &= ~USART_CR1_TCIE;//전송중단
}
else
{
USART1->TDR = sFIFO_pop(&UART1_tx_fifo);
}
}
UART_ER_Control(USART1);
//HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7);
}
void USART3_IRQHandler(void)
{
byte1 a;
if((USART3->ISR & USART_ISR_RXNE) == USART_ISR_RXNE) // 수신버퍼에 데이터가 들어오면
{
a=USART3->RDR;
//USART1->TDR=a;//DEBUG echo loop-back
//USART3->TDR=a;//DEBUG echo loop-back
sFIFO_push(&UART3_rx_fifo,a);
}
if(USART3->ISR & USART_CR1_TCIE)
{
if(sFIFO_Count(&UART3_tx_fifo)==0)
{
USART3->CR1 &= ~USART_CR1_TCIE;//전송중단
}
else
{
USART3->TDR = sFIFO_pop(&UART3_tx_fifo);
}
}
UART_ER_Control(USART3);
}