2018-10-08 04:47 AM
< What I want to do? >
*My Mother tongue is not English. If what I'm writing here is not understandable, let me know. I will fix sentences properly.
< Environment >
< What I tried? >
extracts from main.c
#include "main.h"
#include "stm32l0xx_hal.h"
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
#define txBuf_size 512
#define rxBuf_size 128
char txBuf[txBuf_size];
char rxBuf[rxBuf_size];
char superRxBuf[2000];
uint8_t rxFlag = 0;
uint16_t rxIndex = 0;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void);
void Func_3G_Comm(char *Cmd);
extern void initialise_monitor_handles(void);
int main(void)
{
initialise_monitor_handles(); // Initialize printf func
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
/* Perform the initial configuration in 3G module */
Func_3G_Comm("AT&K3"); // Set hardware flow control
Func_3G_Comm("AT+KTCPCLOSE=1"); // Close TCP1 connection
Func_3G_Comm("AT+KTCPDEL=1"); // Close Delete TCP1 connection
Func_3G_Comm("AT+GPSSTOP"); // Stop GPS
Func_3G_Comm("AT+GPSNMEA=01,,0"); // Stop receiving GPS NMEA data
Func_3G_Comm("AT+CGATT=0"); // PS detachment
Func_3G_Comm("AT+KCNXCFG=1,\"GPRS\",\"***.com\",\"***.com\",\"***\""); // Configure TCP Connection
Func_3G_Comm("AT+CGDCONT=4,\"IP\",\"***.com\""); // Configure GPRS
Func_3G_Comm("AT+KCNXPROFILE=1"); // Configure current profile connection
Func_3G_Comm("AT+KGNSSAD=1"); // Configure GNSS antenna detection
Func_3G_Comm("AT+CGATT=1"); // PS attachment
Func_3G_Comm("AT+KTCPCFG=1,0,\"xxxxxx.com\",16650"); // Configure TCP Connection
Func_3G_Comm("AT+KCNXUP=1"); // Bring up PDP connection
Func_3G_Comm("AT+KTCPCNX=1"); // Start TCP connection
while (1)
{
}
}
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* Enable DMA controller clock */
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel2_3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
}
void Func_3G_Comm(char *Cmd)
{
memset(txBuf, '\0', txBuf_size);
memset(rxBuf, '\0', rxBuf_size);
snprintf(txBuf, txBuf_size, "%s\r\n", Cmd);
HAL_UART_Transmit(&huart1, (uint8_t *)txBuf, strlen(txBuf), 0xFFFF);
HAL_UART_Receive_DMA(&huart1, (uint8_t*)&rxBuf_IT, 1);
HAL_SuspendTick();
for(rxFlag=0;rxFlag==0;)
{
HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}
HAL_ResumeTick();
HAL_TIM_Base_Stop_IT(&htim2);
printf("%s\n",rxBuf);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
HAL_TIM_Base_Stop_IT(&htim2);
if(UartHandle->Instance==USART1){
rxBuf[rxIndex] = rxBuf_IT;
rxIndex++;
}
HAL_TIM_Base_Start_IT(&htim2);
HAL_UART_Receive_DMA(&huart1, (uint8_t*)&rxBuf_IT, 1);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) {
rxFlag = 1;
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
}
}
extracts from stm32l0xx_it.c
void DMA1_Channel2_3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
}
*modification: Func_3G_Comm => LTE_Comm
2018-10-08 05:16 AM
For a communication based on variable-length packets in both directions, DMA seems a quite unfavourable approach.
An interrupt based system, with an end-character detection in the RX interrupt handler to signal complete packets, would IMHO fit better.
2018-10-08 05:52 AM
For this kind of application, DMA for transmit may be OK but reception almost certainly requires a different (interrupt-based) approach.
2018-10-08 06:43 AM
Thank you for your advice!
OK. I'll try to use interrupt func
>> AvaTar
I tried an approach like one you explained; an end-character detection in the RX interrupt handler. However, I didn't come up with a good idea.
one example of rxBuf is like below
AT&K3\r\r\nOK\r\n\r\n+PBREADY\r\n
there are several "\r\n", so it's hard to detect the end of message.
2018-10-08 07:08 AM
As I understand it, each "\r\n" terminates an individual message. The reaction depends on the context.
I did not work much with the AT command set, but I think every message is supposed to be terminated with a "\r\n".
That would signal the reception of a complete message, which is then handed to the syntax check.
If that works out well (i.e. proper command), and the semantics are right (expected command in this context, with proper parameters), one could advance the protocol state machine accordingly.
I had used this method with e.g. Modbus and NMEA0183.
My interrupt routine only checked for "\r\n", everything else was done in the main loop (out of interrupt context).
2018-10-08 07:42 AM
Your code does not compile because identifier "3G_Comm" begins with a digit.
Please show the actual code which compiles.
-- pa
2018-10-08 08:40 AM
>>Pavel
It's a mistake. The original name is "LTE_Comm". I'm developing with 3G module, but will use LTE module in the future so the function is named with "LTE" originally. This is confusing so I modified only the function name. I changed "3G_Comm" to "Func_3G_Comm" and made sure that the function name is complied.
2018-10-08 05:36 PM
I cant see where you reset the timecount for timer 2.
2018-10-09 08:11 AM
>> AvaTar
Thank you for your advice.
In 3G module case, it can add "\r\n" other than in end of a sentence. So detection by catching "\r\n"may be difficult.
2018-10-09 08:17 AM
It think removing a lot of the HAL nonsense, and just managing the peripheral and buffers in an interrupt, will reduce complexity by an order of magnitude or two.