quinta-feira, 10 de setembro de 2020

LOM204 - UTILIZANDO COMO OPENCPU - DS3231

 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