Add modbus module (currently not work)

This commit is contained in:
vlad 2022-03-26 20:31:51 +03:00
parent 4746b6269c
commit cf049a6101
11 changed files with 621 additions and 27 deletions

View File

@ -66,6 +66,18 @@ typedef enum {
START, STOP
} OptStates;
extern OptStates opt_state;
extern uint16_t modbus_cnt;
#define DEVICE_CONTROL 0x01
#define DEVICE_CNT modbus_cnt
#define DEVICE_MIN_RECEIVE_PULSES 5
#define DEVICE_MAX_LOST_PULSES 20
#define DEVICE_MIN_PULSE_WIDTH 250
#define DEVICE_MAX_PULSE_WIDTH 750
typedef struct {} ModbusRegistersStruct;
extern ModbusRegistersStruct ModbusRegisters;
/* USER CODE END Private defines */
#ifdef __cplusplus

36
Core/Inc/modbus_crc.h Normal file
View File

@ -0,0 +1,36 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbcrc.h,v 1.5 2006/12/07 22:10:34 wolti Exp $
*/
#ifndef _MB_CRC_H
#define _MB_CRC_H
CRC_t usMBCRC16( UCHAR * pucFrame, USHORT usLen );
#endif

84
Core/Inc/modbus_lib.h Normal file
View File

@ -0,0 +1,84 @@
#define MODBUS_LIB_MAX_BUFFER 256
/* ----------------------- Defines ------------------------------------------*/
#define MB_ADDRESS_BROADCAST ( 0 ) /*! Modbus broadcast address. */
#define MB_ADDRESS_MIN ( 1 ) /*! Smallest possible slave address. */
#define MB_ADDRESS_MAX ( 247 ) /*! Biggest possible slave address. */
#define MB_FUNC_NONE ( 0 )
#define MB_FUNC_READ_COILS ( 1 )
#define MB_FUNC_READ_DISCRETE_INPUTS ( 2 )
#define MB_FUNC_WRITE_SINGLE_COIL ( 5 )
#define MB_FUNC_WRITE_MULTIPLE_COILS ( 15 )
#define MB_FUNC_READ_HOLDING_REGISTERS ( 3 )
#define MB_FUNC_READ_INPUT_REGISTER ( 4 )
#define MB_FUNC_WRITE_REGISTER ( 6 )
#define MB_FUNC_WRITE_MULTIPLE_REGISTERS ( 16 )
#define MB_FUNC_READWRITE_MULTIPLE_REGISTERS ( 23 )
#define MB_FUNC_DIAG_READ_EXCEPTION ( 7 )
#define MB_FUNC_DIAG_DIAGNOSTIC ( 8 )
#define MB_FUNC_DIAG_GET_COM_EVENT_CNT ( 11 )
#define MB_FUNC_DIAG_GET_COM_EVENT_LOG ( 12 )
#define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 )
#define MB_FUNC_ERROR ( 128 )
/*----------------------- Response types ------------------------------*/
#define MBUS_RESPONSE_OK 0x00
#define MBUS_RESPONSE_NONE 0xFF
/* MBUS_RESPONSE_ILLEGAL_FUNCTION
The function code received in the query is not an allowable action
for the server. This may be because the function code is only
applicable to newerdevices, and was not implemented in the unit
selected. It could also indicate that the serveris in the wrong state to
process a request of this type, for example because it is
unconfigured and is being asked to return register values.
*/
#define MBUS_RESPONSE_ILLEGAL_FUNCTION 0x01
/* MBUS_RESPONSE_ILLEGAL_DATA_ADDRESS
The data address received in the query is not an allowable address
for the server. More specifically, the combination of reference number
and transfer length is invalid. For a controller with 100 registers,
the PDU addresses the first register as 0, and the last one as 99. If
a request is submitted with a starting register address of 96 and a
quantity of registers of 4, then this request will successfully
operate (address-wise at least) on registers 96, 97, 98, 99. If
a request is submitted with a starting register address of 96 and
a quantity of registers of 5, then this request will fail with
Exception Code 0x02 Illegal Data Address since it attempts to
operate on registers 96, 97, 98, 99 and 100, and there is no
register with address 100.
*/
#define MBUS_RESPONSE_ILLEGAL_DATA_ADDRESS 0x02
/* A value contained in the query data field is not an allowable value
for server. This indicates a fault in the structure of the remainder of
a complex request, such as that the implied length is
incorrect. It specifically does NOT mean that a data item submitted for
storage in a register has a value outside the expectation of the application
program, since the MODBUS protocol is unaware of the significance of
any particular val ue of any particular register.
*/
#define MBUS_RESPONSE_ILLEGAL_DATA_VALUE 0x03
/*
An unrecoverable error occurred while the server
was attempting to perform the requested action.
*/
#define MBUS_RESPONSE_SERVICE_DEVICE_FAILURE 0x04
#define MB_ADDRESS_HOLDING_REGISTER_OFFSET (40001)
typedef struct ModbusConfig_t{
uint16_t address;
} ModbusConfig_t;
extern uint8_t g_modbus_lib_received_telegram[MODBUS_LIB_MAX_BUFFER];
extern uint16_t g_modbus_lib_received_length;
extern int modbus_lib_init(ModbusConfig_t*);
extern void modbus_lib_append_data(uint8_t);
extern void modbus_lib_end_of_telegram(void);
extern uint16_t modbus_lib_send_error(int error_code);
extern int modbus_lib_transport_write(uint8_t* buffer, uint16_t length);
extern uint16_t modbus_lib_read_handler(uint16_t la);
extern uint16_t modbus_lib_write_handler(uint16_t la, uint16_t value);

View File

@ -0,0 +1,10 @@
#ifndef _MODBUS_LIB_H_
#define _MODBUS_LIB_H_
#include <stdint.h>
/* ----------------------- Defines ------------------------------------------*/
#define MODBUS_LIB_MIN_TELEGRAM_SIZE 4 /*!< Minimum size of a Modbus RTU frame. */
#endif // _MODBUS_LIB_H_

21
Core/Inc/port.h Normal file
View File

@ -0,0 +1,21 @@
#include <stdint.h>
typedef unsigned char BOOL;
typedef unsigned char UCHAR;
typedef char CHAR;
typedef unsigned int USHORT;
typedef int SHORT;
typedef unsigned long ULONG;
typedef long LONG;
typedef union {
struct {
uint8_t low;
uint8_t high;
} bytes;
uint16_t value;
} CRC_t, MbDataField;

View File

@ -41,12 +41,15 @@
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
OptStates opt_state = STOP;
ModbusRegistersStruct ModbusRegisters;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@ -55,6 +58,8 @@ static void MX_GPIO_Init(void);
static void MX_TIM4_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
@ -95,6 +100,8 @@ int main(void)
MX_TIM4_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
@ -191,6 +198,7 @@ static void MX_TIM2_Init(void)
htim2.Init.Prescaler = 72;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 5000;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
@ -220,12 +228,63 @@ static void MX_TIM2_Init(void)
{
Error_Handler();
}
sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
/**
* @brief TIM4 Initialization Function
* @param None
@ -318,6 +377,39 @@ static void MX_USART1_UART_Init(void)
}
/**
* @brief USART2 Initialization Function
* @param None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None

98
Core/Src/modbus_crc.c Normal file
View File

@ -0,0 +1,98 @@
/*
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
* Copyright (c) 2006 Christian Walter <wolti@sil.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* File: $Id: mbcrc.c,v 1.7 2007/02/18 23:50:27 wolti Exp $
*/
/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
static const UCHAR aucCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};
static const UCHAR aucCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};
CRC_t
usMBCRC16( UCHAR * pucFrame, USHORT usLen )
{
UCHAR ucCRCHi = 0xFF;
UCHAR ucCRCLo = 0xFF;
int iIndex;
while( usLen-- )
{
iIndex = ucCRCLo ^ *( pucFrame++ );
ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] );
ucCRCHi = aucCRCLo[iIndex];
}
return ( CRC_t ){ .bytes.high = ucCRCHi, .bytes.low = ucCRCLo };
}

141
Core/Src/modbus_lib.c Normal file
View File

@ -0,0 +1,141 @@
/*******************************************************
*
* Implementation reference:
*
* http://www.mayor.de/lian98/doc.en/html/u_mbusser-rtu_struct.htm
* https://www.modbustools.com/modbus.html
*
* Example telegrams:
* Read holding registers: 010300000002c40b (read 2 registers starting from 40001)
* Read holding registers: 0103000000044409 (read 4 registers starting from 40001)
*
* Write single register: 01060000007bc9e9 (write "123" to register 40001)
*
* Write multiple registers: 01100000000204007b0237c300
*
*******************************************************/
#include "modbus_lib_types.h"
#include "modbus_lib.h"
#include "port.h"
#include "modbus_crc.h"
uint8_t g_modbus_lib_received_telegram[MODBUS_LIB_MAX_BUFFER];
uint16_t g_modbus_lib_received_length = 0;
uint8_t g_modbus_lib_exception_occurred = 0;
ModbusConfig_t* config;
int modbus_lib_init(ModbusConfig_t* cfg){
config = cfg;
return 0;
}
void modbus_lib_append_data(uint8_t byte){
if (g_modbus_lib_received_length < MODBUS_LIB_MAX_BUFFER){
g_modbus_lib_received_telegram[g_modbus_lib_received_length++] = byte;
}
}
void modbus_lib_end_of_telegram(){
(void) 0; // debugger: p/x *g_modbus_lib_received_telegram@g_modbus_lib_received_length
// Check length
if (g_modbus_lib_received_length < MODBUS_LIB_MIN_TELEGRAM_SIZE){
modbus_lib_send_error(MBUS_RESPONSE_NONE);
return;
}
// Check CRC
CRC_t expected = usMBCRC16(g_modbus_lib_received_telegram, g_modbus_lib_received_length-2);
UCHAR got_low = g_modbus_lib_received_telegram[g_modbus_lib_received_length-2];
UCHAR got_high = g_modbus_lib_received_telegram[g_modbus_lib_received_length-1];
if ((expected.bytes.low != got_low) || (expected.bytes.high != got_high)){
modbus_lib_send_error(MBUS_RESPONSE_NONE);
return;
}
// Check address
if (config->address != g_modbus_lib_received_telegram[0]){
modbus_lib_send_error(MBUS_RESPONSE_NONE);
return;
}
// Telegram is okay, call the relevant handler
// -------------------------------------------
uint8_t outgoing_telegram[MODBUS_LIB_MAX_BUFFER];
uint16_t oindex = 0;
outgoing_telegram[oindex++] = config->address;
volatile MbDataField start_addr, count, res, addr, value;
switch (g_modbus_lib_received_telegram[1]){
case MB_FUNC_READ_HOLDING_REGISTERS:
start_addr.bytes.high = g_modbus_lib_received_telegram[2];
start_addr.bytes.low = g_modbus_lib_received_telegram[3];
count.bytes.high = g_modbus_lib_received_telegram[4];
count.bytes.low = g_modbus_lib_received_telegram[5];
outgoing_telegram[oindex++] = g_modbus_lib_received_telegram[1]; // function code
outgoing_telegram[oindex++] = count.value * 2; // byte count
for (uint16_t i=0; i < count.value; i++){
res.value = modbus_lib_read_handler(start_addr.value + i + MB_ADDRESS_HOLDING_REGISTER_OFFSET);
if (g_modbus_lib_exception_occurred){
g_modbus_lib_exception_occurred = 0;
return;
}
outgoing_telegram[oindex++] = res.bytes.high;
outgoing_telegram[oindex++] = res.bytes.low;
}
CRC_t crc = usMBCRC16(outgoing_telegram, oindex);
outgoing_telegram[oindex++] = crc.bytes.low;
outgoing_telegram[oindex++] = crc.bytes.high;
modbus_lib_transport_write(outgoing_telegram, oindex);
break;
case MB_FUNC_WRITE_REGISTER:
addr.bytes.high = g_modbus_lib_received_telegram[2];
addr.bytes.low = g_modbus_lib_received_telegram[3];
value.bytes.high = g_modbus_lib_received_telegram[4];
value.bytes.low = g_modbus_lib_received_telegram[5];
if (modbus_lib_write_handler(addr.value + MB_ADDRESS_HOLDING_REGISTER_OFFSET, value.value) == 0){
// success
// normal response is the echo of received telegram
modbus_lib_transport_write(g_modbus_lib_received_telegram, g_modbus_lib_received_length);
} else {
// error
g_modbus_lib_exception_occurred = 0;
}
break;
default:
// unimplemented
modbus_lib_send_error(MBUS_RESPONSE_SERVICE_DEVICE_FAILURE);
g_modbus_lib_exception_occurred = 0;
return;
}
g_modbus_lib_received_length = 0;
}
#define MB_EXCEPTION_LENGTH 5
uint16_t modbus_lib_send_error(int error_code){
if (error_code != MBUS_RESPONSE_NONE){
g_modbus_lib_exception_occurred = 1;
uint8_t res[MB_EXCEPTION_LENGTH] = {
config->address,
g_modbus_lib_received_telegram[1] | 0x80,
error_code
};
CRC_t crc = usMBCRC16(res, MB_EXCEPTION_LENGTH - 2);
res[MB_EXCEPTION_LENGTH - 2] = crc.bytes.low;
res[MB_EXCEPTION_LENGTH - 1] = crc.bytes.high;
modbus_lib_transport_write(res, MB_EXCEPTION_LENGTH);
}
g_modbus_lib_received_length = 0;
return -1;
}

View File

@ -101,13 +101,15 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM2 GPIO Configuration
PA0-WKUP ------> TIM2_CH1
PA15 ------> TIM2_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
__HAL_AFIO_REMAP_TIM2_PARTIAL_1();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 14, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
@ -115,6 +117,17 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
/* USER CODE END TIM2_MspInit 1 */
}
else if(htim_base->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
else if(htim_base->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
@ -170,9 +183,9 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
__HAL_RCC_TIM2_CLK_DISABLE();
/**TIM2 GPIO Configuration
PA0-WKUP ------> TIM2_CH1
PA15 ------> TIM2_CH1
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15);
/* TIM2 interrupt DeInit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
@ -180,6 +193,17 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(htim_base->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(htim_base->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */
@ -230,6 +254,33 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
/* USER CODE END USART1_MspInit 1 */
}
else if(huart->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
}
@ -259,6 +310,24 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
/* USER CODE END USART1_MspDeInit 1 */
}
else if(huart->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
}

View File

@ -213,15 +213,29 @@ void TIM2_IRQHandler(void)
_state_counter = 0;
LED_GPIO_Port->BSRR = LED_Pin;
}
// задний фронт, убывающий
if (sr & TIM_SR_CC2IF) {
uint32_t ccr = TIM2->CCR2;
if (ccr >= DEVICE_MIN_PULSE_WIDTH && ccr <= DEVICE_MAX_PULSE_WIDTH) {
// можно считать что это импульс
if (_state_counter > DEVICE_MIN_RECEIVE_PULSES) {
LED_GPIO_Port->BSRR = (uint32_t)LED_Pin << 16;
opt_state = START;
} else {
_state_counter++;
}
}
// else {
// // какое-то говно, а не импульс
// // ну я ничего не делаю
// }
}
// передний возрастающий фронт
// тут по сути надо обнулить CNT, и вроде все
if (sr & TIM_SR_CC1IF) {
TIM2->SR = TIM_SR_CC1IF;
TIM2->CNT = 0; // обнуляем счетчик таймера
if (_state_counter > 20) {
LED_GPIO_Port->BSRR = (uint32_t)LED_Pin << 16;
opt_state = START;
} else {
_state_counter++;
}
}
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);

View File

@ -7,25 +7,31 @@ Mcu.IP0=NVIC
Mcu.IP1=RCC
Mcu.IP2=SYS
Mcu.IP3=TIM2
Mcu.IP4=TIM4
Mcu.IP5=USART1
Mcu.IPNb=6
Mcu.IP4=TIM3
Mcu.IP5=TIM4
Mcu.IP6=USART1
Mcu.IP7=USART2
Mcu.IPNb=8
Mcu.Name=STM32F103C(8-B)Tx
Mcu.Package=LQFP48
Mcu.Pin0=PD0-OSC_IN
Mcu.Pin1=PD1-OSC_OUT
Mcu.Pin10=VP_SYS_VS_Systick
Mcu.Pin11=VP_TIM2_VS_ClockSourceINT
Mcu.Pin12=VP_TIM4_VS_ClockSourceINT
Mcu.Pin2=PA0-WKUP
Mcu.Pin3=PB12
Mcu.Pin4=PA9
Mcu.Pin5=PA10
Mcu.Pin6=PA13
Mcu.Pin7=PA14
Mcu.Pin8=PB5
Mcu.Pin9=PB6
Mcu.PinsNb=13
Mcu.Pin10=PB5
Mcu.Pin11=PB6
Mcu.Pin12=VP_SYS_VS_Systick
Mcu.Pin13=VP_TIM2_VS_ClockSourceINT
Mcu.Pin14=VP_TIM2_VS_indirect_ch1
Mcu.Pin15=VP_TIM3_VS_ClockSourceINT
Mcu.Pin16=VP_TIM4_VS_ClockSourceINT
Mcu.Pin2=PA2
Mcu.Pin3=PA3
Mcu.Pin4=PB12
Mcu.Pin5=PA9
Mcu.Pin6=PA10
Mcu.Pin7=PA13
Mcu.Pin8=PA14
Mcu.Pin9=PA15
Mcu.PinsNb=17
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F103C8Tx
@ -43,13 +49,17 @@ NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true
NVIC.TIM2_IRQn=true\:14\:0\:true\:false\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
PA0-WKUP.Signal=S_TIM2_CH1_ETR
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA15.Signal=S_TIM2_CH1_ETR
PA2.Mode=Asynchronous
PA2.Signal=USART2_TX
PA3.Mode=Asynchronous
PA3.Signal=USART2_RX
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB12.GPIOParameters=GPIO_Label
@ -119,8 +129,9 @@ SH.S_TIM4_CH1.0=TIM4_CH1,PWM Generation1 CH1
SH.S_TIM4_CH1.ConfNb=1
TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
TIM2.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1
TIM2.Channel-Input_Capture2_from_TI1_63=TIM_CHANNEL_2
TIM2.ICFilter_CH1=1
TIM2.IPParameters=Channel-Input_Capture1_from_TI1,ICFilter_CH1,Prescaler,Period,AutoReloadPreload
TIM2.IPParameters=Channel-Input_Capture1_from_TI1,ICFilter_CH1,Prescaler,Period,AutoReloadPreload,Channel-Input_Capture2_from_TI1_63
TIM2.Period=5000
TIM2.Prescaler=72
TIM4.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
@ -130,10 +141,16 @@ TIM4.Prescaler=72
TIM4.Pulse-PWM\ Generation1\ CH1=500
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
USART2.IPParameters=VirtualMode
USART2.VirtualMode=VM_ASYNC
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM2_VS_ClockSourceINT.Mode=Internal
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
VP_TIM2_VS_indirect_ch1.Mode=Input_Capture2_from_TI1_63
VP_TIM2_VS_indirect_ch1.Signal=TIM2_VS_indirect_ch1
VP_TIM3_VS_ClockSourceINT.Mode=Internal
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
VP_TIM4_VS_ClockSourceINT.Mode=Internal
VP_TIM4_VS_ClockSourceINT.Signal=TIM4_VS_ClockSourceINT
board=custom