UTILIZANDO LOM204A02 COMO OPENCPU
O objetivo deste BLOG é demonstrar como é possível interagir com o módulo LOM204A02 via API mode ou seja, com acesso aos comandos via API e utilizá-lo como OPENCPU.
Neste exemplo, utilizaremos o LOM204A2 (EVL20XA R1) para requisitar a hora via barramento I2C, será utilizado o relógio da Dallas DS3231.
A programação será via KEIL C, o mesmo utilizado para compilar o firmware dos comandos CLI.
Neste exemplo, não será transmitido para LoRaWAN a hora, pois o objetivo é apenas ler o DS3231 via I2c.
O Real Time Clock (RTC) DS3231 é um relógio de tempo real de alta precisão e baixo consumo de energia. Em sua placa vem embutido um sensor de temperatura e um cristal oscilador para melhorar sua exatidão.
A ligação foi realizada desta forma
ALGUMAS MUDANÇAS REALIZADAS PARA FUNCIONAR I2C
1) EM stm32l0xx_hal_conf.h, descomentar
#define HAL_I2C_MODULE_ENABLED
2) EM stm32l0xx_hal_msp.h, incluir
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_I2C1;
3) EM main.c configurar pinos SDA e SCL (HAL_I2C_MspInit)
FOI MANTIDO LORAWAN STACK JUNTO PARA MOSTRAR QUE AINDA ESTA VIVO!
//----------------------------------------------------------------------------
// Project Name : LoRa WAN
//----------------------------------------------------------------------------
// File Name : Main.c
//----------------------------------------------------------------------------
// Processor : STM32L071CZY WLCSP
// Compiler : uVision V5.20.0.0
// RF Transceiver : SX1276
// Frequency : 917 ~ 928Mhz
// Modulation : LoRa
// Version : H/W(1.3), LIB(2.02)
// Company : Seongji Industrial
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// History
//
// DATE Author Version COMMENT
// 2018/06/01 KSH,CYH V1.00 Start
// 2018/07/31 KSH,CYH V1.01 Modify : AFA, LRW 5D,Select Channel Add : AU915,
// 2018/08/01 KSH,CYH V1.01 Add cmd: Channel Mask, Rx Delay1, Data rate, Join Accept Delay1, Repeater support, Activation, ABP setting value
// Modify : JOIN_START, API_MODE
// 2019/11/07 KSH V2.02 Add cmd: save Fcnt, sw reset, bug fix
//----------------------------------------------------------------------------
#define MAIN_C_
#include <stddef.h>
#include <string.h>
#include "stm32l0xx_hal.h"
#include <math.h>
#include "board.h"
#include "Utilities.h"
#include "misc.h"
#include "process.h"
#include "timer.h"
#include "init.h"
#include "timer.h"
#include "main.h"
#include "WISOL_API.h"
I2C_HandleTypeDef hi2c1;
#define RTC_ADDRESS (0x68 << 1)
//#define RTC_ADDRESS (0x38 << 1)
uint8_t data[8];
uint8_t seconds, minutes, hours, days, date, month, year;
char msgBuffer[19]; //2017-02-23 10:10:10
uint8_t B2D(uint8_t);
uint8_t B2D(uint8_t byte)
{
uint8_t low, high;
low = byte & 0x0F;
high = ((byte >> 4) & 0x0F) * 10;
return high + low;
}
/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB9 ------> I2C1_SDA
PB8 ------> I2C1_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
/**
* @brief I2C1 Initialization Function
* @param None
* @retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00000708;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
//Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
//Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
//Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
//--------------------------------------------------------------------------------------------------
// Setting description for DEFINE
//
// LED3_TRX : Led3 lturns on at Tx/Rx
// RS485_USE : RE pin control when using RS485 converter.
//-------------------------------------------------------------------------------------------------
#if defined (RS485_USE)
uint8_t Rs485_en =1;
#endif
/**
* Main application entry point.
*/
//---------------------------------------------------------------------------------------------------------
// Example
//---------------------------------------------------------------------------------------------------------
char* opt1 = "FF00";
char* opt2 = "0000";
char* opt3 = "0000";
char* opt4 = "0000";
char* opt5 = "0000";
char* opt6 = "0000";
uint8_t tx_flag=0;
void Exe_user_fn(void)
{
if( tx_flag ==1)
{
tx_flag =0;
data_Tx(1,1,1,10,"1234567890"); // Tx data (ASCII , Confirmed up, Fport : 1 , datalength : 10, data: 1234567890 )
Wakeup_Timer(&TxUser,User_fn,120000,0U); // Wakes up every 60 seconds and runs User_fn.
}
}
void User_fn(void)
{
tx_flag =1;
}
unsigned char Status_JOIN;
int main(void)
{
Start_Init();
HAL_I2C_MspInit(&hi2c1);
MX_I2C1_Init();
/* Set RTC 2017-02-23 Thur 10:38 */
data[0] = 0x00; //address
data[1] = 0x00; //seconds
data[2] = 0x00; //minutes
data[3] = 0x00; //hours
data[4] = 0x05; //days
data[5] = 0x19; //date
data[6] = 0x04; //month
data[7] = 0x22; //year
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 8, 50);
setClass(0); // Set CLASS C mode.
setChannelMask(opt1, opt2, opt3, opt4, opt5, opt6);
//if( getActivation()==0 ) // If the current mode is OTAA.
//{
// setActivation(1); // set abp mode , If this function is run, module is reseted.
//}
//setAbpDeviceAddress(0x260D0FED);
//setAbpAppSKey((unsigned char *) "76145087FBEEFB6C122C5F36BC82431E", 32);
//setAbpNwkSKey((unsigned char *) "744C5D712578D946DE32E7F05837B40E", 32);
setRxDelay1(5000); // RX1 delay 5s
setRxDelay2(6000); // RX2 delay 6s
JOIN_TIME_START(8); //tenta 8 vezes
JOIN_START(); // Join srart
//Wakeup_Timer(&TxUser,User_fn,120000,0U); // Wakes up every 60 seconds and runs User_fn.
HAL_StatusTypeDef result;
uint8_t i;
while(1)
{
CLI_Command_Process(); // To receive CLI command through serial port(UART)
API_MODE(); // Run LoRa protocol.
//Exe_user_fn();
if(Check_Received_Msg())
{
for (i=1; i<128; i++)
{
result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i<<1), 2, 2);
if (result != HAL_OK) // HAL_ERROR or HAL_BUSY or HAL_TIMEOUT
{
PRINTF("."); // No ACK received at that address
}
if (result == HAL_OK)
{
PRINTF("0x%X", i); // Received an ACK at that address
}
}
PRINTF("\r\n");
PRINTF("PORT: %d\r\n",rx_msg.port); // Get the port of the received message.
PRINTF("RX_MSG : ");
for(uint8_t i =0; i<rx_msg.payload_size; i++)
{
PRINTF("%02x", rx_msg.mac_payload[i]); // Get the payload of the received message.
}
PRINTF("\r\n");
data[0] = 0x00; //register address
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &seconds, 1, 50);
data[0] = 0x01;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &minutes, 1, 50);
data[0] = 0x02;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &hours, 1, 50);
data[0] = 0x03;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &days, 1, 50);
data[0] = 0x04;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &date, 1, 50);
data[0] = 0x05;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &month, 1, 50);
data[0] = 0x06;
HAL_I2C_Master_Transmit(&hi2c1, RTC_ADDRESS, data, 1, 50);
HAL_I2C_Master_Receive(&hi2c1, RTC_ADDRESS|0x01, &year, 1, 50);
sprintf(msgBuffer, "%04d-%02d-%02d %02d:%02d:%02d",
B2D(year)+2000,
B2D(month & 0x1F),
B2D(date & 0x3F),
B2D(hours & 0x07),
B2D(minutes & 0x7F),
B2D(seconds & 0x7F));
PRINTF(msgBuffer);
PRINTF("\r\n");
}
/*
PRINTF("Scanning I2C bus:\r\n");
HAL_StatusTypeDef result;
uint8_t i;
for (i=1; i<128; i++)
{
result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i<<1), 2, 2);
if (result != HAL_OK) // HAL_ERROR or HAL_BUSY or HAL_TIMEOUT
{
PRINTF("."); // No ACK received at that address
}
if (result == HAL_OK)
{
PRINTF("0x%X", i); // Received an ACK at that address
}
}
PRINTF("\r\n");
*/
}
}
void Start_Init(void)
{
HW_SystemClock_Config();
StartNVInit();
BoardInitPeriph( );
BoardInitMcu( );
Var_Init();
sub_process_init(); // set receive mode for uart
#ifdef DEBUG_GPIO
Timer_1ms_Start(IDLE_MODE_TIME_OUT,200,0xff,BIT0_fn); // When a module enters sleep, it no longer works.
#endif
TimerInit( &TxNext, Txnext_fn ); // Do not modify
/*
#if defined (USE_BAND_920)
#ifndef OLD_CLI_COMPATIBILITY_MODE
TimerInit( &Rest_send, restrict_send);
#endif
#endif
*/
nvm_init(); // To read the configuration saved in EEPROM.
Clr_BIT2();
LDO_on();
}
void Restart_Init(void)
{
BoardInitPeriph( );
BoardInitMcu( );
Var_Init();
sub_process_init(); // set receive mode for uart
#ifdef DEBUG_GPIO
Timer_1ms_Start(IDLE_MODE_TIME_OUT,200,0xff,BIT0_fn); // When a module enters sleep, it no longer works.
#endif
TimerInit( &TxNext, Txnext_fn ); // Do not modify
/*
#if defined (USE_BAND_920)
#ifndef OLD_CLI_COMPATIBILITY_MODE
TimerInit( &Rest_send, restrict_send);
#endif
#endif
*/
nvm_init(); // To read the configuration saved in EEPROM.
// PRINTF("KSH TEST3\r\n");
Clr_BIT2();
LDO_on();
}
4) Compilando
5) Fazendo o UPLOAD
Enfim, aqui está o link do Projeto
Melhorias do projeto acima
REDUÇÃO DA VELOCIDADE DE FREQUÊNCIA DO I²C
MELHORIA DO TEMPO DE SUBIDA E DESCIDA DO CLOCK DO I²C
REDUÇÃO DO CLOCK DE PCLK1 (I²C)
REDUÇÃO DO CLOCK PLL (PLLCLK)
PRINT DA TELA DE CONFIGURAÇÃO DE CLOCK DO STM CUBE MX
RESULTADO FINAL DO CLOCK (PINO SCL) MEDIDO COM O OSCILOSCÓPIO
Projeto
Fontes:
Datasheets
SCH_EVL20xA_R1_170630.pdf
Datasheet_LOM204A_V0.1_20190715.pdf
Dúvidas
suporte@smartcore.com.br
Agradecimento
Tiago Fernandes da Silva |
Departamento de Engenharia de Pesquisa e Desenvolvimento - (P&D) |
+55 (35) 3471-2555 Ramal: 0237 |
tiago@mg.sense.com.br |
Sense Eletrônica Ltda |
Av. Joaquim Moreira Carneiro, 600, Santa Rita do Sapucaí-MG |
https://www.sense.com.br |
Sobre a SMARTCORE
A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br