#include <string.h>
#include "stm32f7_uart_dma.h"
#include "../MyModules/RingQueue.h"
#include "../MyModules/Protocol.h"
/** @addtogroup STM32F7xx_LL_Examples
* @{
*/
/** @addtogroup USART_Communication_TxRx_DMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DMA_RECEPT_DATA_SIZE 1 //73×Ö½Ú´¥·¢DMAÖжÏ
#define DMA_DATA_BUF_SIZE 128 //DMA·¢ËÍ»º´æ´óС
/* Private macro -------------------------------------------------------------*/
#define USE_USART2//USE_USART3//USE_USART2
#ifdef USE_USART3
#define UART_GPIOx GPIOD
#define UART_TX_PIN LL_GPIO_PIN_8
#define UART_RX_PIN LL_GPIO_PIN_9
#define UART_NUM USART3
#define LL_APB1_GRP1_PERIPH_USARTx LL_APB1_GRP1_PERIPH_USART3
#define LL_RCC_USARTx_CLKSOURCE_PCLK1 LL_RCC_USART3_CLKSOURCE_PCLK1
#define UART_SEND_STREAM LL_DMA_STREAM_3
#define UART_RECV_STREAM LL_DMA_STREAM_1
#define UART_DMA_CHANNEL LL_DMA_CHANNEL_4
#define UART_DMA_NUM DMA1
#else
#define UART_GPIOx GPIOD
#define UART_TX_PIN LL_GPIO_PIN_5
#define UART_RX_PIN LL_GPIO_PIN_6
#define UART_NUM USART2
#define LL_APB1_GRP1_PERIPH_USARTx LL_APB1_GRP1_PERIPH_USART2
#define LL_RCC_USARTx_CLKSOURCE_PCLK1 LL_RCC_USART2_CLKSOURCE_PCLK1
#define UART_SEND_STREAM LL_DMA_STREAM_6
#define UART_RECV_STREAM LL_DMA_STREAM_5
#define UART_DMA_CHANNEL LL_DMA_CHANNEL_4
#define UART_DMA_NUM DMA1
#endif
/* Private variables ---------------------------------------------------------*/
/* Buffer used for transmission */
uint8_t cTxDMABuffer[DMA_DATA_BUF_SIZE];
/* Buffer used for reception */
uint8_t cRxDMABuffer[DMA_DATA_BUF_SIZE];
#define RX_BUF_MAX_SIZE (MAX_CMD_SIZE*10)
static unsigned char RingBuffer[RX_BUF_MAX_SIZE];
static RING_QUEUE RingQueue;
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the DMA Channels for TX and RX transfers
* @note This function is used to :
* -1- Enable DMA1 clock
* -2- Configure NVIC for DMA transfer complete/error interrupts
* -3- Configure DMA TX channel functional parameters
* -4- Configure DMA RX channel functional parameters
* -5- Enable transfer complete/error interrupts
* @param None
* @retval None
*/
void Configure_USART2_DMA(void)
{
/* DMA1 used for USART3 Transmission and Reception
*/
/* (1) Enable the clock of DMA1 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/* (2) Configure NVIC for DMA transfer complete/error interrupts */
#ifdef USE_USART3
NVIC_SetPriority(DMA1_Stream3_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream3_IRQn);
NVIC_SetPriority(DMA1_Stream1_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream1_IRQn);
#else
NVIC_SetPriority(DMA1_Stream5_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream5_IRQn);
NVIC_SetPriority(DMA1_Stream6_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream6_IRQn);
#endif
/* (3) Configure the DMA functional parameters for transmission */
LL_DMA_SetChannelSelection(UART_DMA_NUM, UART_SEND_STREAM, UART_DMA_CHANNEL);
LL_DMA_ConfigTransfer(UART_DMA_NUM, UART_SEND_STREAM,
LL_DMA_DIRECTION_MEMORY_TO_PERIPH |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(UART_DMA_NUM, UART_SEND_STREAM,
(uint32_t)cTxDMABuffer,
LL_USART_DMA_GetRegAddr(UART_NUM, LL_USART_DMA_REG_DATA_TRANSMIT),
LL_DMA_GetDataTransferDirection(UART_DMA_NUM, UART_SEND_STREAM));
LL_DMA_SetDataLength(UART_DMA_NUM, UART_SEND_STREAM, DMA_DATA_BUF_SIZE);
/* (4) Configure the DMA functional parameters for reception */
LL_DMA_SetChannelSelection(UART_DMA_NUM, UART_RECV_STREAM, UART_DMA_CHANNEL);
LL_DMA_ConfigTransfer(UART_DMA_NUM, UART_RECV_STREAM,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL | //LL_DMA_MODE_NORMAL | //LL_DMA_MODE_CIRCULAR ÖжÏÑ»·
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(UART_DMA_NUM, UART_RECV_STREAM,
LL_USART_DMA_GetRegAddr(UART_NUM, LL_USART_DMA_REG_DATA_RECEIVE),
(uint32_t)cRxDMABuffer,
LL_DMA_GetDataTransferDirection(UART_DMA_NUM, UART_RECV_STREAM));
LL_DMA_SetDataLength(UART_DMA_NUM, UART_RECV_STREAM, DMA_RECEPT_DATA_SIZE);
/* (5) Enable DMA transfer complete/error interrupts */
LL_DMA_EnableIT_TC(UART_DMA_NUM, UART_SEND_STREAM);
LL_DMA_EnableIT_TE(UART_DMA_NUM, UART_SEND_STREAM);
LL_DMA_EnableIT_TC(UART_DMA_NUM, UART_RECV_STREAM);
LL_DMA_EnableIT_TE(UART_DMA_NUM, UART_RECV_STREAM);
}
/**
* @brief This function configures USARTx Instance.
* @note This function is used to :
* -1- Enable GPIO clock and configures the USART3 pins.
* -2- Enable the USART3 peripheral clock and clock source.
* -3- Configure USART3 functional parameters.
* -4- Enable USART3.
* @note Peripheral configuration is minimal configuration from reset values.
* Thus, some useless LL unitary functions calls below are provided as
* commented examples - setting is default configuration from reset.
* @param None
* @retval None
*/
void Configure_USART2(void)
{
/* (1) Enable GPIO clock and configures the USART pins **********************/
/* Enable the peripheral clock of GPIO Port */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART_GPIOx, UART_TX_PIN, LL_GPIO_MODE_ALTERNATE);
#ifdef USE_USART3
LL_GPIO_SetAFPin_8_15(UART_GPIOx, UART_TX_PIN, LL_GPIO_AF_7);
#else
LL_GPIO_SetAFPin_0_7(UART_GPIOx, UART_TX_PIN, LL_GPIO_AF_7);
#endif
LL_GPIO_SetPinSpeed(UART_GPIOx, UART_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART_GPIOx, UART_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART_GPIOx, UART_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART_GPIOx, UART_RX_PIN, LL_GPIO_MODE_ALTERNATE);
#ifdef USE_USART3
LL_GPIO_SetAFPin_8_15(UART_GPIOx, UART_RX_PIN, LL_GPIO_AF_7);
#else
LL_GPIO_SetAFPin_0_7(UART_GPIOx, UART_RX_PIN, LL_GPIO_AF_7);
#endif
LL_GPIO_SetPinSpeed(UART_GPIOx, UART_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART_GPIOx, UART_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART_GPIOx, UART_RX_PIN, LL_GPIO_PULL_UP);
/* (2) Enable USART3 peripheral clock and clock source ****************/
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USARTx);
/* Set clock source */
LL_RCC_SetUSARTClockSource(LL_RCC_USARTx_CLKSOURCE_PCLK1);
/* (3) Configure USART3 functional parameters ********************************/
/* Disable USART prior modifying configuration registers */
/* Note: Commented as corresponding to Reset value */
// LL_USART_Disable(UART_NUM);
/* TX/RX direction */
LL_USART_SetTransferDirection(UART_NUM, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(UART_NUM, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
/* No Hardware Flow control */
/* Reset value is LL_USART_HWCONTROL_NONE */
// LL_USART_SetHWFlowCtrl(UART_NUM, LL_USART_HWCONTROL_NONE);
/* Oversampling by 16 */
/* Reset value is LL_USART_OVERSAMPLING_16 */
// LL_USART_SetOverSampling(UART_NUM, LL_USART_OVERSAMPLING_16);
/* Set Baudrate to 115200 using APB frequency set to 54000000 Hz */
/* Frequency available for USART peripheral can also be calculated through LL RCC macro */
/* Ex :
Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance
In this example, Peripheral Clock is expected to be equal to 54000000 Hz => equal to SystemCoreClock/4
*/
LL_USART_SetBaudRate(UART_NUM, SystemCoreClock/4, LL_USART_OVERSAMPLING_16, 115200);
/* (4) Enable UART_NUM **********************************************************/
LL_USART_Enable(UART_NUM);
}
/**
* @brief This function initiates TX and RX DMA transfers by enabling DMA channels
* @param None
* @retval None
*/
void USART2_StartTransfers(void)
{
unsigned char errm;
// ³õʼ»¯»º´æÇø
RingQueueInit(&RingQueue, RingBuffer, RX_BUF_MAX_SIZE, &errm);
/* Enable DMA RX Interrupt */
LL_USART_EnableDMAReq_RX(UART_NUM);
/* Enable DMA TX Interrupt */
LL_USART_EnableDMAReq_TX(UART_NUM);
/* Enable DMA Channel Rx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_RECV_STREAM);
/* Enable DMA Channel Tx */
//LL_DMA_EnableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
int SerialDMASend(unsigned char *p_data,unsigned int size)
{
if(size > 0)
{
memcpy(cTxDMABuffer,p_data,size);
LL_DMA_SetDataLength(UART_DMA_NUM, UART_SEND_STREAM, size);
/* Enable DMA Channel Tx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
return 0;
}
int SerialDMARecv(unsigned char *p_data,unsigned int max_size)
{
unsigned char err;
unsigned int size = 0;
if (0 == RingQueueGetLength(&RingQueue))
return 0;
size = RingQueueOut(&RingQueue, p_data, max_size, &err);
if (err == RQ_ERR_NONE)
{
return size;
}
return 0;
}
#ifdef USE_MTI
//УÑéºÍ£ºBID....CheckSUM,ÀÛ¼ÓΪ0
char CalChecksum(char *p_data,unsigned int size)
{
unsigned int i = 0;
char result = 0;
for(i = 1;i < size;i++)
result += p_data[i];
return result;
}
int GetCommandFromRingQueue(unsigned char *p_data,unsigned int max_size)
{
unsigned char ring_err = 0;
unsigned int ring_size = 0;
volatile unsigned int cmd_length = 0;
if (RingQueueGetLength(&RingQueue) < 5) //Ö¸Á¶È×îСΪ5×Ö½Ú
return -1;
ring_size = RingQueueLook(&RingQueue, p_data, 5, &ring_err);//ÏÈÈ¡³ö5×Ö½ÚÍ·Êý¾Ý
if(ring_size != 5)
return -2;
if((p_data[0] != PACKAGE_HEAD_PREAMBLE)||(p_data[1] != PACKAGE_HEAD_BID))//Æ¥ÅäÍ·Á½¸ö×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -3;
}
cmd_length = CMD_FREAMBLE_SIZE + CMD_BID_SIZE + CMD_MID_SIZE + CMD_LEN_SIZE;
if(p_data[3] <= PACKAGE_LEN_STANDARD)//±ê×¼Êý¾Ý
{
cmd_length += p_data[3];
}
else if(p_data[3] == PACKAGE_LEN_EXTENDED)//À©Õ¹Êý¾Ý
{
cmd_length += CMD_EXTLEN_SIZE;
cmd_length += p_data[4]*256+p_data[5];
RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);//£¿ÏÈÅ×Æú0xFFÀ©Õ¹Êý¾Ý´¦Àí
return -8;
}
else
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -4;//´íÎóµÄ³¤¶ÈÊý¾Ý
}
//cmd_length += CMD_IND_ID_SIZE;//IND ID Size
cmd_length += CMD_CHECKSUM_SIZE;//CheckSum Size
ring_size = RingQueueLook(&RingQueue, p_data, cmd_length, &ring_err);
if(ring_size < cmd_length)
return -5;//¶ÁÈ¡µ½µÄÊý¾ÝÁ¿²»×ãÒ»Ö¡
if(0 != (unsigned char)CalChecksum((char*)p_data,cmd_length))
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -6;//УÑé´íÎó
}
ring_size = RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);
if (ring_err != RQ_ERR_NONE)
{
return -7; //Êý¾Ý¶ÁÈ¡´íÎó
}
return cmd_length;//ring_size;
}
#else
/*!
* Compute a CRC for a specified buffer.
* \param[in] pBuffer Read only buffer to compute the CRC on.
* \param[in] bufferSize Buffer size in bytes.
* \return The computed 16 bit CRC.
*/
unsigned short calcCRC(const void *pBuffer, unsigned short bufferSize)
{
const unsigned char *pBytesArray = (const unsigned char*)pBuffer;
unsigned short poly = 0x8408;
unsigned short crc = 0;
unsigned char carry;
unsigned char i_bits;
unsigned short j;
for (j =0; j < bufferSize; j++)
{
crc = crc ^ pBytesArray[j];
for (i_bits = 0; i_bits < 8; i_bits++)
{
carry = crc & 1;
crc = crc / 2;
if (carry)
{
crc = crc^poly;
}
}
}
return crc;
}
int GetCommandFromRingQueue(unsigned char *p_data,unsigned int max_size)
{
unsigned char ring_err = 0;
unsigned int ring_size = 0;
volatile unsigned int cmd_length = 0;
unsigned short check_sum = 0;
if (RingQueueGetLength(&RingQueue) < MIN_CMD_SIZE) //Ö¸Á¶È×îСΪMIN_CMD_SIZE×Ö½Ú
return -1;
ring_size = RingQueueLook(&RingQueue, p_data, MIN_CMD_SIZE, &ring_err);//ÏÈÈ¡³öMIN_CMD_SIZE×Ö½ÚÍ·Êý¾Ý
if(ring_size != MIN_CMD_SIZE)
return -2;
if((p_data[0] != PACKAGE_HEAD_SYNC_1)||(p_data[1] != PACKAGE_HEAD_SYNC_2))//Æ¥ÅäÍ·Á½¸ö×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -3;
}
cmd_length = MIN_CMD_SIZE + p_data[4] + p_data[5]*256;
if(cmd_length > CMD_MAX_DATA_SIZE)
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//³¤¶È²»¶ÔÅ×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -4;//´íÎóµÄ³¤¶ÈÊý¾Ý
}
ring_size = RingQueueLook(&RingQueue, p_data, cmd_length, &ring_err);
if(ring_size < cmd_length)
return -5;//¶ÁÈ¡µ½µÄÊý¾ÝÁ¿²»×ãÒ»Ö¡
check_sum = p_data[cmd_length - 3] + p_data[cmd_length - 2]*256;
if(check_sum != (unsigned short)calcCRC((char*)(p_data + 2),cmd_length - 5))//´ÓµÚ2×Ö½Ú¿ªÊ¼¼ÆËã,²»¼ÆËãͷβºÍ×ÔÉí5×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -6;//УÑé´íÎó
}
ring_size = RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);
if (ring_err != RQ_ERR_NONE)
{
return -7; //Êý¾Ý¶ÁÈ¡´íÎó
}
return ring_size;
}
#endif
/**
* @brief Function called from DMA1 IRQ Handler when Tx transfer is completed
* @param None
* @retval None
*/
void DMA1_TransmitComplete_Callback(void)
{
/* DMA Tx transfer completed */
/* Disable UART_DMA_NUM Tx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
/**
* @brief Function called from DMA1 IRQ Handler when Rx transfer is completed
* @param None
* @retval None
*/
void DMA1_ReceiveComplete_Callback(void)
{
unsigned char err;
/* DMA Rx transfer completed */
//NVIC_DisableIRQ(DMA1_Stream5_IRQn);
//LL_USART_DisableDMAReq_RX(UART_NUM);
/* Disable UART_DMA_NUM Rx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_RECV_STREAM);
RingQueueIn(&RingQueue, (pRQTYPE)cRxDMABuffer,DMA_RECEPT_DATA_SIZE, RQ_OPTION_WHEN_FULL_DISCARD_FIRST, &err);
//SerialDMASend(cRxDMABuffer,DMA_RECEPT_DATA_SIZE);
//uart3_send(cRxDMABuffer, DMA_RECEPT_DATA_SIZE);
/* Enable DMA Channel Rx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_RECV_STREAM);
//LL_USART_EnableDMAReq_RX(UART_NUM);
//NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}
/**
* @brief Function called in case of error detected in USART IT Handler
* @param None
* @retval None
*/
void USART_TransferError_Callback(void)
{
/* Disable UART_DMA_NUM Tx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_SEND_STREAM);
/* Disable UART_DMA_NUM Rx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_RECV_STREAM);
/* Set LED1 to Blinking mode to indicate error occurs */
//LED_Blinking(LED_BLINK_ERROR);
}
#include "stm32f7_uart_dma.h"
#include "../MyModules/RingQueue.h"
#include "../MyModules/Protocol.h"
/** @addtogroup STM32F7xx_LL_Examples
* @{
*/
/** @addtogroup USART_Communication_TxRx_DMA
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DMA_RECEPT_DATA_SIZE 1 //73×Ö½Ú´¥·¢DMAÖжÏ
#define DMA_DATA_BUF_SIZE 128 //DMA·¢ËÍ»º´æ´óС
/* Private macro -------------------------------------------------------------*/
#define USE_USART2//USE_USART3//USE_USART2
#ifdef USE_USART3
#define UART_GPIOx GPIOD
#define UART_TX_PIN LL_GPIO_PIN_8
#define UART_RX_PIN LL_GPIO_PIN_9
#define UART_NUM USART3
#define LL_APB1_GRP1_PERIPH_USARTx LL_APB1_GRP1_PERIPH_USART3
#define LL_RCC_USARTx_CLKSOURCE_PCLK1 LL_RCC_USART3_CLKSOURCE_PCLK1
#define UART_SEND_STREAM LL_DMA_STREAM_3
#define UART_RECV_STREAM LL_DMA_STREAM_1
#define UART_DMA_CHANNEL LL_DMA_CHANNEL_4
#define UART_DMA_NUM DMA1
#else
#define UART_GPIOx GPIOD
#define UART_TX_PIN LL_GPIO_PIN_5
#define UART_RX_PIN LL_GPIO_PIN_6
#define UART_NUM USART2
#define LL_APB1_GRP1_PERIPH_USARTx LL_APB1_GRP1_PERIPH_USART2
#define LL_RCC_USARTx_CLKSOURCE_PCLK1 LL_RCC_USART2_CLKSOURCE_PCLK1
#define UART_SEND_STREAM LL_DMA_STREAM_6
#define UART_RECV_STREAM LL_DMA_STREAM_5
#define UART_DMA_CHANNEL LL_DMA_CHANNEL_4
#define UART_DMA_NUM DMA1
#endif
/* Private variables ---------------------------------------------------------*/
/* Buffer used for transmission */
uint8_t cTxDMABuffer[DMA_DATA_BUF_SIZE];
/* Buffer used for reception */
uint8_t cRxDMABuffer[DMA_DATA_BUF_SIZE];
#define RX_BUF_MAX_SIZE (MAX_CMD_SIZE*10)
static unsigned char RingBuffer[RX_BUF_MAX_SIZE];
static RING_QUEUE RingQueue;
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the DMA Channels for TX and RX transfers
* @note This function is used to :
* -1- Enable DMA1 clock
* -2- Configure NVIC for DMA transfer complete/error interrupts
* -3- Configure DMA TX channel functional parameters
* -4- Configure DMA RX channel functional parameters
* -5- Enable transfer complete/error interrupts
* @param None
* @retval None
*/
void Configure_USART2_DMA(void)
{
/* DMA1 used for USART3 Transmission and Reception
*/
/* (1) Enable the clock of DMA1 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/* (2) Configure NVIC for DMA transfer complete/error interrupts */
#ifdef USE_USART3
NVIC_SetPriority(DMA1_Stream3_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream3_IRQn);
NVIC_SetPriority(DMA1_Stream1_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream1_IRQn);
#else
NVIC_SetPriority(DMA1_Stream5_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream5_IRQn);
NVIC_SetPriority(DMA1_Stream6_IRQn, 0);
NVIC_EnableIRQ(DMA1_Stream6_IRQn);
#endif
/* (3) Configure the DMA functional parameters for transmission */
LL_DMA_SetChannelSelection(UART_DMA_NUM, UART_SEND_STREAM, UART_DMA_CHANNEL);
LL_DMA_ConfigTransfer(UART_DMA_NUM, UART_SEND_STREAM,
LL_DMA_DIRECTION_MEMORY_TO_PERIPH |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(UART_DMA_NUM, UART_SEND_STREAM,
(uint32_t)cTxDMABuffer,
LL_USART_DMA_GetRegAddr(UART_NUM, LL_USART_DMA_REG_DATA_TRANSMIT),
LL_DMA_GetDataTransferDirection(UART_DMA_NUM, UART_SEND_STREAM));
LL_DMA_SetDataLength(UART_DMA_NUM, UART_SEND_STREAM, DMA_DATA_BUF_SIZE);
/* (4) Configure the DMA functional parameters for reception */
LL_DMA_SetChannelSelection(UART_DMA_NUM, UART_RECV_STREAM, UART_DMA_CHANNEL);
LL_DMA_ConfigTransfer(UART_DMA_NUM, UART_RECV_STREAM,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
LL_DMA_PRIORITY_HIGH |
LL_DMA_MODE_NORMAL | //LL_DMA_MODE_NORMAL | //LL_DMA_MODE_CIRCULAR ÖжÏÑ»·
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_BYTE |
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_ConfigAddresses(UART_DMA_NUM, UART_RECV_STREAM,
LL_USART_DMA_GetRegAddr(UART_NUM, LL_USART_DMA_REG_DATA_RECEIVE),
(uint32_t)cRxDMABuffer,
LL_DMA_GetDataTransferDirection(UART_DMA_NUM, UART_RECV_STREAM));
LL_DMA_SetDataLength(UART_DMA_NUM, UART_RECV_STREAM, DMA_RECEPT_DATA_SIZE);
/* (5) Enable DMA transfer complete/error interrupts */
LL_DMA_EnableIT_TC(UART_DMA_NUM, UART_SEND_STREAM);
LL_DMA_EnableIT_TE(UART_DMA_NUM, UART_SEND_STREAM);
LL_DMA_EnableIT_TC(UART_DMA_NUM, UART_RECV_STREAM);
LL_DMA_EnableIT_TE(UART_DMA_NUM, UART_RECV_STREAM);
}
/**
* @brief This function configures USARTx Instance.
* @note This function is used to :
* -1- Enable GPIO clock and configures the USART3 pins.
* -2- Enable the USART3 peripheral clock and clock source.
* -3- Configure USART3 functional parameters.
* -4- Enable USART3.
* @note Peripheral configuration is minimal configuration from reset values.
* Thus, some useless LL unitary functions calls below are provided as
* commented examples - setting is default configuration from reset.
* @param None
* @retval None
*/
void Configure_USART2(void)
{
/* (1) Enable GPIO clock and configures the USART pins **********************/
/* Enable the peripheral clock of GPIO Port */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD);
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART_GPIOx, UART_TX_PIN, LL_GPIO_MODE_ALTERNATE);
#ifdef USE_USART3
LL_GPIO_SetAFPin_8_15(UART_GPIOx, UART_TX_PIN, LL_GPIO_AF_7);
#else
LL_GPIO_SetAFPin_0_7(UART_GPIOx, UART_TX_PIN, LL_GPIO_AF_7);
#endif
LL_GPIO_SetPinSpeed(UART_GPIOx, UART_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART_GPIOx, UART_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART_GPIOx, UART_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART_GPIOx, UART_RX_PIN, LL_GPIO_MODE_ALTERNATE);
#ifdef USE_USART3
LL_GPIO_SetAFPin_8_15(UART_GPIOx, UART_RX_PIN, LL_GPIO_AF_7);
#else
LL_GPIO_SetAFPin_0_7(UART_GPIOx, UART_RX_PIN, LL_GPIO_AF_7);
#endif
LL_GPIO_SetPinSpeed(UART_GPIOx, UART_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART_GPIOx, UART_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART_GPIOx, UART_RX_PIN, LL_GPIO_PULL_UP);
/* (2) Enable USART3 peripheral clock and clock source ****************/
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USARTx);
/* Set clock source */
LL_RCC_SetUSARTClockSource(LL_RCC_USARTx_CLKSOURCE_PCLK1);
/* (3) Configure USART3 functional parameters ********************************/
/* Disable USART prior modifying configuration registers */
/* Note: Commented as corresponding to Reset value */
// LL_USART_Disable(UART_NUM);
/* TX/RX direction */
LL_USART_SetTransferDirection(UART_NUM, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(UART_NUM, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
/* No Hardware Flow control */
/* Reset value is LL_USART_HWCONTROL_NONE */
// LL_USART_SetHWFlowCtrl(UART_NUM, LL_USART_HWCONTROL_NONE);
/* Oversampling by 16 */
/* Reset value is LL_USART_OVERSAMPLING_16 */
// LL_USART_SetOverSampling(UART_NUM, LL_USART_OVERSAMPLING_16);
/* Set Baudrate to 115200 using APB frequency set to 54000000 Hz */
/* Frequency available for USART peripheral can also be calculated through LL RCC macro */
/* Ex :
Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance
In this example, Peripheral Clock is expected to be equal to 54000000 Hz => equal to SystemCoreClock/4
*/
LL_USART_SetBaudRate(UART_NUM, SystemCoreClock/4, LL_USART_OVERSAMPLING_16, 115200);
/* (4) Enable UART_NUM **********************************************************/
LL_USART_Enable(UART_NUM);
}
/**
* @brief This function initiates TX and RX DMA transfers by enabling DMA channels
* @param None
* @retval None
*/
void USART2_StartTransfers(void)
{
unsigned char errm;
// ³õʼ»¯»º´æÇø
RingQueueInit(&RingQueue, RingBuffer, RX_BUF_MAX_SIZE, &errm);
/* Enable DMA RX Interrupt */
LL_USART_EnableDMAReq_RX(UART_NUM);
/* Enable DMA TX Interrupt */
LL_USART_EnableDMAReq_TX(UART_NUM);
/* Enable DMA Channel Rx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_RECV_STREAM);
/* Enable DMA Channel Tx */
//LL_DMA_EnableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
int SerialDMASend(unsigned char *p_data,unsigned int size)
{
if(size > 0)
{
memcpy(cTxDMABuffer,p_data,size);
LL_DMA_SetDataLength(UART_DMA_NUM, UART_SEND_STREAM, size);
/* Enable DMA Channel Tx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
return 0;
}
int SerialDMARecv(unsigned char *p_data,unsigned int max_size)
{
unsigned char err;
unsigned int size = 0;
if (0 == RingQueueGetLength(&RingQueue))
return 0;
size = RingQueueOut(&RingQueue, p_data, max_size, &err);
if (err == RQ_ERR_NONE)
{
return size;
}
return 0;
}
#ifdef USE_MTI
//УÑéºÍ£ºBID....CheckSUM,ÀÛ¼ÓΪ0
char CalChecksum(char *p_data,unsigned int size)
{
unsigned int i = 0;
char result = 0;
for(i = 1;i < size;i++)
result += p_data[i];
return result;
}
int GetCommandFromRingQueue(unsigned char *p_data,unsigned int max_size)
{
unsigned char ring_err = 0;
unsigned int ring_size = 0;
volatile unsigned int cmd_length = 0;
if (RingQueueGetLength(&RingQueue) < 5) //Ö¸Á¶È×îСΪ5×Ö½Ú
return -1;
ring_size = RingQueueLook(&RingQueue, p_data, 5, &ring_err);//ÏÈÈ¡³ö5×Ö½ÚÍ·Êý¾Ý
if(ring_size != 5)
return -2;
if((p_data[0] != PACKAGE_HEAD_PREAMBLE)||(p_data[1] != PACKAGE_HEAD_BID))//Æ¥ÅäÍ·Á½¸ö×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -3;
}
cmd_length = CMD_FREAMBLE_SIZE + CMD_BID_SIZE + CMD_MID_SIZE + CMD_LEN_SIZE;
if(p_data[3] <= PACKAGE_LEN_STANDARD)//±ê×¼Êý¾Ý
{
cmd_length += p_data[3];
}
else if(p_data[3] == PACKAGE_LEN_EXTENDED)//À©Õ¹Êý¾Ý
{
cmd_length += CMD_EXTLEN_SIZE;
cmd_length += p_data[4]*256+p_data[5];
RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);//£¿ÏÈÅ×Æú0xFFÀ©Õ¹Êý¾Ý´¦Àí
return -8;
}
else
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -4;//´íÎóµÄ³¤¶ÈÊý¾Ý
}
//cmd_length += CMD_IND_ID_SIZE;//IND ID Size
cmd_length += CMD_CHECKSUM_SIZE;//CheckSum Size
ring_size = RingQueueLook(&RingQueue, p_data, cmd_length, &ring_err);
if(ring_size < cmd_length)
return -5;//¶ÁÈ¡µ½µÄÊý¾ÝÁ¿²»×ãÒ»Ö¡
if(0 != (unsigned char)CalChecksum((char*)p_data,cmd_length))
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -6;//УÑé´íÎó
}
ring_size = RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);
if (ring_err != RQ_ERR_NONE)
{
return -7; //Êý¾Ý¶ÁÈ¡´íÎó
}
return cmd_length;//ring_size;
}
#else
/*!
* Compute a CRC for a specified buffer.
* \param[in] pBuffer Read only buffer to compute the CRC on.
* \param[in] bufferSize Buffer size in bytes.
* \return The computed 16 bit CRC.
*/
unsigned short calcCRC(const void *pBuffer, unsigned short bufferSize)
{
const unsigned char *pBytesArray = (const unsigned char*)pBuffer;
unsigned short poly = 0x8408;
unsigned short crc = 0;
unsigned char carry;
unsigned char i_bits;
unsigned short j;
for (j =0; j < bufferSize; j++)
{
crc = crc ^ pBytesArray[j];
for (i_bits = 0; i_bits < 8; i_bits++)
{
carry = crc & 1;
crc = crc / 2;
if (carry)
{
crc = crc^poly;
}
}
}
return crc;
}
int GetCommandFromRingQueue(unsigned char *p_data,unsigned int max_size)
{
unsigned char ring_err = 0;
unsigned int ring_size = 0;
volatile unsigned int cmd_length = 0;
unsigned short check_sum = 0;
if (RingQueueGetLength(&RingQueue) < MIN_CMD_SIZE) //Ö¸Á¶È×îСΪMIN_CMD_SIZE×Ö½Ú
return -1;
ring_size = RingQueueLook(&RingQueue, p_data, MIN_CMD_SIZE, &ring_err);//ÏÈÈ¡³öMIN_CMD_SIZE×Ö½ÚÍ·Êý¾Ý
if(ring_size != MIN_CMD_SIZE)
return -2;
if((p_data[0] != PACKAGE_HEAD_SYNC_1)||(p_data[1] != PACKAGE_HEAD_SYNC_2))//Æ¥ÅäÍ·Á½¸ö×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -3;
}
cmd_length = MIN_CMD_SIZE + p_data[4] + p_data[5]*256;
if(cmd_length > CMD_MAX_DATA_SIZE)
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//³¤¶È²»¶ÔÅ×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -4;//´íÎóµÄ³¤¶ÈÊý¾Ý
}
ring_size = RingQueueLook(&RingQueue, p_data, cmd_length, &ring_err);
if(ring_size < cmd_length)
return -5;//¶ÁÈ¡µ½µÄÊý¾ÝÁ¿²»×ãÒ»Ö¡
check_sum = p_data[cmd_length - 3] + p_data[cmd_length - 2]*256;
if(check_sum != (unsigned short)calcCRC((char*)(p_data + 2),cmd_length - 5))//´ÓµÚ2×Ö½Ú¿ªÊ¼¼ÆËã,²»¼ÆËãͷβºÍ×ÔÉí5×Ö½Ú
{
RingQueueOut(&RingQueue, p_data, 2, &ring_err);//Å×Æú´íÎóµÄÁ½¸öÊý¾ÝÍ·
return -6;//УÑé´íÎó
}
ring_size = RingQueueOut(&RingQueue, p_data, cmd_length, &ring_err);
if (ring_err != RQ_ERR_NONE)
{
return -7; //Êý¾Ý¶ÁÈ¡´íÎó
}
return ring_size;
}
#endif
/**
* @brief Function called from DMA1 IRQ Handler when Tx transfer is completed
* @param None
* @retval None
*/
void DMA1_TransmitComplete_Callback(void)
{
/* DMA Tx transfer completed */
/* Disable UART_DMA_NUM Tx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_SEND_STREAM);
}
/**
* @brief Function called from DMA1 IRQ Handler when Rx transfer is completed
* @param None
* @retval None
*/
void DMA1_ReceiveComplete_Callback(void)
{
unsigned char err;
/* DMA Rx transfer completed */
//NVIC_DisableIRQ(DMA1_Stream5_IRQn);
//LL_USART_DisableDMAReq_RX(UART_NUM);
/* Disable UART_DMA_NUM Rx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_RECV_STREAM);
RingQueueIn(&RingQueue, (pRQTYPE)cRxDMABuffer,DMA_RECEPT_DATA_SIZE, RQ_OPTION_WHEN_FULL_DISCARD_FIRST, &err);
//SerialDMASend(cRxDMABuffer,DMA_RECEPT_DATA_SIZE);
//uart3_send(cRxDMABuffer, DMA_RECEPT_DATA_SIZE);
/* Enable DMA Channel Rx */
LL_DMA_EnableStream(UART_DMA_NUM, UART_RECV_STREAM);
//LL_USART_EnableDMAReq_RX(UART_NUM);
//NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}
/**
* @brief Function called in case of error detected in USART IT Handler
* @param None
* @retval None
*/
void USART_TransferError_Callback(void)
{
/* Disable UART_DMA_NUM Tx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_SEND_STREAM);
/* Disable UART_DMA_NUM Rx Channel */
LL_DMA_DisableStream(UART_DMA_NUM, UART_RECV_STREAM);
/* Set LED1 to Blinking mode to indicate error occurs */
//LED_Blinking(LED_BLINK_ERROR);
}