Compare commits

...

2 Commits

Author SHA1 Message Date
snow
8f5dc1cadd temp ok, need test 2024-04-25 10:20:39 +08:00
snow
e90bd57a59 add pile logic, need verify 2024-04-15 18:04:26 +08:00
62 changed files with 6373 additions and 1681 deletions

View File

@ -1,26 +1,32 @@
set(SRCS set(SRCS
"uart_example.c"
"main.c" "main.c"
"utils.c" "modbus-tcp.c"
"./modbus/ModbusS.c" "can_network.c"
"./modbus/uart0_modbus_slave.c" "./stm32/ads1220.c"
"./peripheral/led.c" "./stm32/bl0939.c"
"./peripheral/config/fram.c" "./stm32/capture.c"
"./peripheral/config/config.c" "./stm32/comm.c"
"./peripheral/flow/ads1220.c" "./stm32/depth.c"
"./peripheral/flow/input_type2.c" "./stm32/fram.c"
"./peripheral/flow/flow.c" "./stm32/flow.c"
"./peripheral/bl0939.c" "./stm32/utils.c"
"./peripheral/depth.c" "./stm32/config.c"
"./peripheral/depth_.c" "./stm32/ModbusS.c"
"./stm32/ModbusM.c"
"./stm32/uart0_modbus_slave.c"
"./stm32/pile_id.c"
"./stm32/led.c"
"./communication_pad/wifi_softap.c"
"./communication_pad/udp_server.c"
"./communication_pad/ble_gatts_server.c"
"./communication_pad/communication_pad.c"
#"C:\Espressif\frameworks\esp-idf-v4.4.5\components\bt\include"
) )
set(INCLUDE_DIRS set(INCLUDE_DIRS "." "./communication_pad/inc")
"." "./inc"
"./modbus/inc"
"./peripheral/inc"
"./peripheral/flow/inc"
"./peripheral/config/inc"
)
idf_component_register(SRCS ${SRCS} idf_component_register(SRCS ${SRCS}
INCLUDE_DIRS ${INCLUDE_DIRS}) INCLUDE_DIRS ${INCLUDE_DIRS})

257
main/can_network.c Normal file
View File

@ -0,0 +1,257 @@
/* TWAI Network Slave Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
/*
* The following example demonstrates a slave node in a TWAI network. The slave
* node is responsible for sending data messages to the master. The example will
* execute multiple iterations, with each iteration the slave node will do the
* following:
* 1) Start the TWAI driver
* 2) Listen for ping messages from master, and send ping response
* 3) Listen for start command from master
* 4) Send data messages to master and listen for stop command
* 5) Send stop response to master
* 6) Stop the TWAI driver
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/twai.h"
#include "can_network.h"
/* --------------------- Definitions and static variables ------------------ */
// Example Configuration
#define DATA_PERIOD_MS 50
#define NO_OF_ITERS 3
#define ITER_DELAY_MS 1000
#define RX_TASK_PRIO 41 // Receiving task priority
#define TX_TASK_PRIO 42 // Sending task priority
#define CTRL_TSK_PRIO 10 // Control task priority
#define TX_GPIO_NUM 17
#define RX_GPIO_NUM 18
#define TAG "CAN"
#define ID_MASTER_STOP_CMD 0x0A0
#define ID_MASTER_START_CMD 0x0A1
#define ID_MASTER_PING 0x0A2
#define ID_SLAVE_STOP_RESP 0x0B0
#define ID_SLAVE_DATA 0x0B1
#define ID_SLAVE_PING_RESP 0x0B2
typedef enum
{
TX_SEND_PING_RESP,
TX_SEND_DATA,
TX_SEND_STOP_RESP,
TX_TASK_EXIT,
} tx_task_action_t;
typedef enum
{
RX_RECEIVE_PING,
RX_RECEIVE_START_CMD,
RX_RECEIVE_STOP_CMD,
RX_TASK_EXIT,
} rx_task_action_t;
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL);
// static const twai_message_t ping_resp = {.identifier = ID_SLAVE_PING_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
// static const twai_message_t stop_resp = {.identifier = ID_SLAVE_STOP_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
// Data bytes of data message will be initialized in the transmit task
// twai_message_t data_message = {.identifier = ID_SLAVE_DATA, .data_length_code = 8, .data = {0, 0, 0, 0, 0, 0, 0, 0}};
// static QueueHandle_t tx_task_queue;
// static QueueHandle_t rx_task_queue;
// static SemaphoreHandle_t ctrl_task_sem;
// static SemaphoreHandle_t stop_data_sem;
// static SemaphoreHandle_t done_sem;
/* --------------------------- Tasks and Functions -------------------------- */
static void twai_receive_task(void *arg)
{
twai_message_t rx_msg;
int i;
while (1)
{
char msg_data_str[32];
int index = 0;
esp_err_t err = twai_receive(&rx_msg, portMAX_DELAY);
if (err == ESP_OK)
{
for (i = 0; i < rx_msg.data_length_code; i++)
{
index += sprintf(&msg_data_str[i], "%02x ", rx_msg.data[i]);
}
ESP_LOGI(TAG, "recive msg id=%lx,len=%u,data=[%s]", rx_msg.identifier, rx_msg.data_length_code, msg_data_str);
}
}
}
// static void twai_transmit_task(void *arg)
// {
// while (1)
// {
// tx_task_action_t action;
// xQueueReceive(tx_task_queue, &action, portMAX_DELAY);
// if (action == TX_SEND_PING_RESP)
// {
// // Transmit ping response to master
// twai_transmit(&ping_resp, portMAX_DELAY);
// ESP_LOGI(EXAMPLE_TAG, "Transmitted ping response");
// xSemaphoreGive(ctrl_task_sem);
// }
// else if (action == TX_SEND_DATA)
// {
// // Transmit data messages until stop command is received
// ESP_LOGI(EXAMPLE_TAG, "Start transmitting data");
// while (1)
// {
// // FreeRTOS tick count used to simulate sensor data
// uint32_t sensor_data = xTaskGetTickCount();
// for (int i = 0; i < 4; i++)
// {
// data_message.data[i] = (sensor_data >> (i * 8)) & 0xFF;
// }
// twai_transmit(&data_message, portMAX_DELAY);
// ESP_LOGI(EXAMPLE_TAG, "Transmitted data value %d", sensor_data);
// vTaskDelay(pdMS_TO_TICKS(DATA_PERIOD_MS));
// if (xSemaphoreTake(stop_data_sem, 0) == pdTRUE)
// {
// break;
// }
// }
// }
// else if (action == TX_SEND_STOP_RESP)
// {
// // Transmit stop response to master
// twai_transmit(&stop_resp, portMAX_DELAY);
// ESP_LOGI(EXAMPLE_TAG, "Transmitted stop response");
// xSemaphoreGive(ctrl_task_sem);
// }
// else if (action == TX_TASK_EXIT)
// {
// break;
// }
// }
// vTaskDelete(NULL);
// }
// static void twai_control_task(void *arg)
// {
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// tx_task_action_t tx_action;
// rx_task_action_t rx_action;
// for (int iter = 0; iter < NO_OF_ITERS; iter++)
// {
// ESP_ERROR_CHECK(twai_start());
// ESP_LOGI(EXAMPLE_TAG, "Driver started");
// // Listen of pings from master
// rx_action = RX_RECEIVE_PING;
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// // Send ping response
// tx_action = TX_SEND_PING_RESP;
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// // Listen for start command
// rx_action = RX_RECEIVE_START_CMD;
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// // Start sending data messages and listen for stop command
// tx_action = TX_SEND_DATA;
// rx_action = RX_RECEIVE_STOP_CMD;
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// // Send stop response
// tx_action = TX_SEND_STOP_RESP;
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY);
// // Wait for bus to become free
// twai_status_info_t status_info;
// twai_get_status_info(&status_info);
// while (status_info.msgs_to_tx > 0)
// {
// vTaskDelay(pdMS_TO_TICKS(100));
// twai_get_status_info(&status_info);
// }
// ESP_ERROR_CHECK(twai_stop());
// ESP_LOGI(EXAMPLE_TAG, "Driver stopped");
// vTaskDelay(pdMS_TO_TICKS(ITER_DELAY_MS));
// }
// // Stop TX and RX tasks
// tx_action = TX_TASK_EXIT;
// rx_action = RX_TASK_EXIT;
// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY);
// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY);
// // Delete Control task
// xSemaphoreGive(done_sem);
// vTaskDelete(NULL);
// }
void can_init(void)
{
// Add short delay to allow master it to initialize first
// Create semaphores and tasks
// tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t));
// rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t));
// ctrl_task_sem = xSemaphoreCreateBinary();
// stop_data_sem = xSemaphoreCreateBinary();;
// done_sem = xSemaphoreCreateBinary();;
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
ESP_LOGI(TAG, "Driver installed");
xTaskCreatePinnedToCore(twai_receive_task, "CAN_rx", 1024, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY);
twai_start();
// xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, TX_TASK_PRIO, NULL, tskNO_AFFINITY);
// xTaskCreatePinnedToCore(twai_control_task, "TWAI_ctrl", 4096, NULL, CTRL_TSK_PRIO, NULL, tskNO_AFFINITY);
// Install TWAI driver, trigger tasks to start
// ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
// xSemaphoreGive(ctrl_task_sem); // Start Control task
// xSemaphoreTake(done_sem, portMAX_DELAY); // Wait for tasks to complete
// //Uninstall TWAI driver
// ESP_ERROR_CHECK(twai_driver_uninstall());
// ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
// //Cleanup
// vSemaphoreDelete(ctrl_task_sem);
// vSemaphoreDelete(stop_data_sem);
// vSemaphoreDelete(done_sem);
// vQueueDelete(tx_task_queue);
// vQueueDelete(rx_task_queue);
}

19
main/can_network.h Normal file
View File

@ -0,0 +1,19 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __CAN_NETWORK_H
#define __CAN_NETWORK_H
#ifdef __cplusplus
extern "C" {
#endif
void can_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __HELLOWERLOD_H */
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,687 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/****************************************************************************
*
* This demo showcases creating a GATT database using a predefined attribute table.
* It acts as a GATT server and can send adv data, be connected by client.
* Run the gatt_client demo, the client demo will automatically connect to the gatt_server_service_table demo.
* Client demo will enable GATT server's notify after connection. The two devices will then exchange
* data.
*
****************************************************************************/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "ble_gatts_server.h"
#include "esp_gatt_common_api.h"
#include "stm32/config.h"
#include "stm32/ModbusS.h"
#include "inc/communication_pad.h"
#define GATTS_TABLE_TAG "BLE_GATTS_SERVER"
#define PROFILE_NUM 1
#define PROFILE_APP_IDX 0
#define ESP_APP_ID 0x55
#define SAMPLE_DEVICE_NAME "ESP_GATTS_DEMO"
#define SVC_INST_ID 0
/* The max length of characteristic value. When the GATT client performs a write or prepare write operation,
* the data length must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
*/
#define GATTS_DEMO_CHAR_VAL_LEN_MAX 500
#define PREPARE_BUF_MAX_SIZE 1024
#define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
#define ADV_CONFIG_FLAG (1 << 0)
#define SCAN_RSP_CONFIG_FLAG (1 << 1)
static uint8_t adv_config_done = 0;
uint16_t ble_gatts_handle_table[IDX_NB];
typedef struct {
uint8_t *prepare_buf;
int prepare_len;
} prepare_type_env_t;
static prepare_type_env_t prepare_write_env;
#define CONFIG_SET_RAW_ADV_DATA
#ifdef CONFIG_SET_RAW_ADV_DATA
static uint8_t raw_adv_data[] = {
/* flags */
0x02, 0x01, 0x06,
/* tx power*/
0x02, 0x0a, 0xeb,
/* service uuid */
0x03, 0x03, 0xFF, 0x00,
/* device name */
0x0f, 0x09, 'E', 'S', 'P', '_', 'G', 'A', 'T', 'T', 'S', '_', 'D','E', 'M', 'O'
};
static uint8_t raw_scan_rsp_data[] = {
/* flags */
0x02, 0x01, 0x06,
/* tx power */
0x02, 0x0a, 0xeb,
/* service uuid */
0x03, 0x03, 0xFF,0x00
};
#else
static uint8_t service_uuid[16] = {
/* LSB <--------------------------------------------------------------------------------> MSB */
//first uuid, 16bit, [12],[13] is the value
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
};
/* The length of adv data must be less than 31 bytes */
static esp_ble_adv_data_t adv_data = {
.set_scan_rsp = false,
.include_name = true,
.include_txpower = true,
.min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
.max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec
.appearance = 0x00,
.manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
.p_manufacturer_data = NULL, //test_manufacturer,
.service_data_len = 0,
.p_service_data = NULL,
.service_uuid_len = sizeof(service_uuid),
.p_service_uuid = service_uuid,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
// scan response data
static esp_ble_adv_data_t scan_rsp_data = {
.set_scan_rsp = true,
.include_name = true,
.include_txpower = true,
.min_interval = 0x0006,
.max_interval = 0x0010,
.appearance = 0x00,
.manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
.p_manufacturer_data = NULL, //&test_manufacturer[0],
.service_data_len = 0,
.p_service_data = NULL,
.service_uuid_len = sizeof(service_uuid),
.p_service_uuid = service_uuid,
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
#endif /* CONFIG_SET_RAW_ADV_DATA */
static esp_ble_adv_params_t adv_params = {
.adv_int_min = 0x20,
.adv_int_max = 0x40,
.adv_type = ADV_TYPE_IND,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.channel_map = ADV_CHNL_ALL,
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
struct gatts_profile_inst {
esp_gatts_cb_t gatts_cb;
uint16_t gatts_if;
uint16_t app_id;
uint16_t conn_id;
uint16_t service_handle;
esp_gatt_srvc_id_t service_id;
uint16_t char_handle;
esp_bt_uuid_t char_uuid;
esp_gatt_perm_t perm;
esp_gatt_char_prop_t property;
uint16_t descr_handle;
esp_bt_uuid_t descr_uuid;
};
static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst ble_gatts_profile_tab[PROFILE_NUM] = {
[PROFILE_APP_IDX] = {
.gatts_cb = gatts_profile_event_handler,
.gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
},
};
/* Service */
static const uint16_t GATTS_SERVICE_UUID = 0x00FF;
static const uint16_t GATTS_DATA_READ_WRITE_UUID = 0xFF01;
static const uint16_t GATTS_DATA_NOTIFY_UUID = 0xFF02;
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t data_read_write_value[4] = {0x00};
static const uint8_t data_read_write_ccc[2] = {0x00, 0x00};
static const uint8_t data_notify_val[4] = {0x00};
static const uint8_t data_notify_ccc[2] = {0x00, 0x00};
bool data_notify_enable = false; /* 是否允许数据上报 */
bool is_connected = false; /* 蓝牙是否连接 */
static uint16_t ble_gatts_conn_id = 0xffff;
static esp_gatt_if_t ble_gatts_if = 0xff;
/* Full Database Description - Used to add attributes into the database */
static const esp_gatts_attr_db_t gatt_db[IDX_NB] =
{
// Service Declaration
[IDX_SVC] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID), (uint8_t *)&GATTS_SERVICE_UUID}},
/* Characteristic Declaration */
[IDX_DATA_READ_WRITE_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
/* Characteristic Value */
[IDX_DATA_READ_WRITE_VAL] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_DATA_READ_WRITE_UUID, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(data_read_write_value), (uint8_t *)data_read_write_value}},
/* Client Characteristic Configuration Descriptor */
[IDX_DATA_READ_WRITE_CFG] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
sizeof(uint16_t), sizeof(data_read_write_ccc), (uint8_t *)data_read_write_ccc}},
//SPP - data notify characteristic Declaration
[IDX_DATA_NOTIFY_CHAR] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
//SPP - data notify characteristic Value
[IDX_DATA_NOTIFY_VAL] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_DATA_NOTIFY_UUID, ESP_GATT_PERM_READ,
GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(data_notify_val), (uint8_t *)data_notify_val}},
//SPP - data notify characteristic - Client Characteristic Configuration Descriptor
[IDX_DATA_NOTIFY_CFG] =
{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
sizeof(uint16_t),sizeof(data_notify_ccc), (uint8_t *)data_notify_ccc}},
};
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
switch (event) {
#ifdef CONFIG_SET_RAW_ADV_DATA
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
adv_config_done &= (~ADV_CONFIG_FLAG);
if (adv_config_done == 0){
esp_ble_gap_start_advertising(&adv_params);
}
break;
case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
adv_config_done &= (~SCAN_RSP_CONFIG_FLAG);
if (adv_config_done == 0){
esp_ble_gap_start_advertising(&adv_params);
}
break;
#else
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
adv_config_done &= (~ADV_CONFIG_FLAG);
if (adv_config_done == 0){
esp_ble_gap_start_advertising(&adv_params);
}
break;
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
adv_config_done &= (~SCAN_RSP_CONFIG_FLAG);
if (adv_config_done == 0){
esp_ble_gap_start_advertising(&adv_params);
}
break;
#endif
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
/* advertising start complete event to indicate advertising start successfully or failed */
if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(GATTS_TABLE_TAG, "advertising start failed");
}else{
ESP_LOGI(GATTS_TABLE_TAG, "advertising start successfully");
}
break;
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(GATTS_TABLE_TAG, "Advertising stop failed");
}
else {
ESP_LOGI(GATTS_TABLE_TAG, "Stop adv successfully\n");
}
break;
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
param->update_conn_params.status,
param->update_conn_params.min_int,
param->update_conn_params.max_int,
param->update_conn_params.conn_int,
param->update_conn_params.latency,
param->update_conn_params.timeout);
break;
default:
break;
}
}
void example_prepare_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param)
{
ESP_LOGI(GATTS_TABLE_TAG, "prepare write, handle = %d, value len = %d", param->write.handle, param->write.len);
esp_gatt_status_t status = ESP_GATT_OK;
if (prepare_write_env->prepare_buf == NULL) {
prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
prepare_write_env->prepare_len = 0;
if (prepare_write_env->prepare_buf == NULL) {
ESP_LOGE(GATTS_TABLE_TAG, "%s, Gatt_server prep no mem", __func__);
status = ESP_GATT_NO_RESOURCES;
}
} else {
if(param->write.offset > PREPARE_BUF_MAX_SIZE) {
status = ESP_GATT_INVALID_OFFSET;
} else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
status = ESP_GATT_INVALID_ATTR_LEN;
}
}
/*send response when param->write.need_rsp is true */
if (param->write.need_rsp){
esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t));
if (gatt_rsp != NULL){
gatt_rsp->attr_value.len = param->write.len;
gatt_rsp->attr_value.handle = param->write.handle;
gatt_rsp->attr_value.offset = param->write.offset;
gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len);
esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp);
if (response_err != ESP_OK){
ESP_LOGE(GATTS_TABLE_TAG, "Send response error");
}
free(gatt_rsp);
}else{
ESP_LOGE(GATTS_TABLE_TAG, "%s, malloc failed", __func__);
}
}
if (status != ESP_GATT_OK){
return;
}
memcpy(prepare_write_env->prepare_buf + param->write.offset,
param->write.value,
param->write.len);
prepare_write_env->prepare_len += param->write.len;
}
void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC && prepare_write_env->prepare_buf){
esp_log_buffer_hex(GATTS_TABLE_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
ble_read_data(prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
}else{
ESP_LOGI(GATTS_TABLE_TAG,"ESP_GATT_PREP_WRITE_CANCEL");
}
if (prepare_write_env->prepare_buf) {
free(prepare_write_env->prepare_buf);
prepare_write_env->prepare_buf = NULL;
}
prepare_write_env->prepare_len = 0;
}
static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
switch (event) {
case ESP_GATTS_REG_EVT:{
esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
if (set_dev_name_ret){
ESP_LOGE(GATTS_TABLE_TAG, "set device name failed, error code = %x", set_dev_name_ret);
}
#ifdef CONFIG_SET_RAW_ADV_DATA
esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data));
if (raw_adv_ret){
ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
}
adv_config_done |= ADV_CONFIG_FLAG;
esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data));
if (raw_scan_ret){
ESP_LOGE(GATTS_TABLE_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret);
}
adv_config_done |= SCAN_RSP_CONFIG_FLAG;
#else
//config adv data
esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "config adv data failed, error code = %x", ret);
}
adv_config_done |= ADV_CONFIG_FLAG;
//config scan response data
ret = esp_ble_gap_config_adv_data(&scan_rsp_data);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "config scan response data failed, error code = %x", ret);
}
adv_config_done |= SCAN_RSP_CONFIG_FLAG;
#endif
esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, IDX_NB, SVC_INST_ID);
if (create_attr_ret){
ESP_LOGE(GATTS_TABLE_TAG, "create attr table failed, error code = %x", create_attr_ret);
}
}
break;
case ESP_GATTS_READ_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");
// esp_gatt_rsp_t rsp;
// memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
// rsp.attr_value.handle = param->read.handle;
// rsp.attr_value.len = 4;
// rsp.attr_value.value[0] = 0xde;
// rsp.attr_value.value[1] = 0xed;
// rsp.attr_value.value[2] = 0xbe;
// rsp.attr_value.value[3] = 0xef;
// esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
// ESP_GATT_OK, NULL);
break;
case ESP_GATTS_WRITE_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT, need_rsp=%d", param->write.need_rsp);
if (!param->write.is_prep){
// the data length of gattc write must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
ESP_LOGI(GATTS_TABLE_TAG, "GATT_WRITE_EVT, handle = %d, value len = %d, value :", param->write.handle, param->write.len);
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
if (ble_gatts_handle_table[IDX_DATA_READ_WRITE_VAL] == param->write.handle)
{
ble_read_data(param->write.value, param->write.len);
}
if (ble_gatts_handle_table[IDX_DATA_NOTIFY_CFG] == param->write.handle && param->write.len == 2){
uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
if (descr_value == 0x0001){
ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
data_notify_enable = true;
}//else if (descr_value == 0x0002){
// ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
// }
else if (descr_value == 0x0000){
ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
data_notify_enable = false;
}else{
ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
}
}
/* send response when param->write.need_rsp is true*/
if (param->write.need_rsp){
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
}
}else{
/* handle prepare write */
example_prepare_write_event_env(gatts_if, &prepare_write_env, param);
}
break;
case ESP_GATTS_EXEC_WRITE_EVT:
// the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT");
example_exec_write_event_env(&prepare_write_env, param);
break;
case ESP_GATTS_MTU_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
break;
case ESP_GATTS_CONF_EVT:
// ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle);
break;
case ESP_GATTS_START_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
break;
case ESP_GATTS_CONNECT_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
esp_log_buffer_hex(GATTS_TABLE_TAG, param->connect.remote_bda, 6);
esp_ble_conn_update_params_t conn_params = {0};
memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
/* For the iOS system, please refer to Apple official documents about the BLE connection parameters restrictions. */
conn_params.latency = 0;
conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms
conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms
conn_params.timeout = 400; // timeout = 400*10ms = 4000ms
//start sent the update connection parameters to the peer device.
esp_ble_gap_update_conn_params(&conn_params);
is_connected = true;
ble_gatts_conn_id = param->connect.conn_id;
ble_gatts_if = gatts_if;
break;
case ESP_GATTS_DISCONNECT_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason);
esp_ble_gap_start_advertising(&adv_params);
is_connected = false;
break;
case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
if (param->add_attr_tab.status != ESP_GATT_OK){
ESP_LOGE(GATTS_TABLE_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
}
else if (param->add_attr_tab.num_handle != IDX_NB){
ESP_LOGE(GATTS_TABLE_TAG, "create attribute table abnormally, num_handle (%d) \
doesn't equal to IDX_NB(%d)", param->add_attr_tab.num_handle, IDX_NB);
}
else {
ESP_LOGI(GATTS_TABLE_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
memcpy(ble_gatts_handle_table, param->add_attr_tab.handles, sizeof(ble_gatts_handle_table));
esp_ble_gatts_start_service(ble_gatts_handle_table[IDX_SVC]);
}
break;
}
case ESP_GATTS_STOP_EVT:
case ESP_GATTS_OPEN_EVT:
case ESP_GATTS_CANCEL_OPEN_EVT:
case ESP_GATTS_CLOSE_EVT:
case ESP_GATTS_LISTEN_EVT:
case ESP_GATTS_CONGEST_EVT:
case ESP_GATTS_UNREG_EVT:
case ESP_GATTS_DELETE_EVT:
default:
break;
}
}
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
/* If event is register event, store the gatts_if for each profile */
if (event == ESP_GATTS_REG_EVT) {
if (param->reg.status == ESP_GATT_OK) {
ble_gatts_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
} else {
ESP_LOGE(GATTS_TABLE_TAG, "reg app failed, app_id %04x, status %d",
param->reg.app_id,
param->reg.status);
return;
}
}
do {
int idx;
for (idx = 0; idx < PROFILE_NUM; idx++) {
/* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
if (gatts_if == ESP_GATT_IF_NONE || gatts_if == ble_gatts_profile_tab[idx].gatts_if) {
if (ble_gatts_profile_tab[idx].gatts_cb) {
ble_gatts_profile_tab[idx].gatts_cb(event, gatts_if, param);
}
}
}
} while (0);
}
void ble_gatts_server_init(void)
{
esp_err_t ret;
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_init();
if (ret) {
ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_enable();
if (ret) {
ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
return;
}
ret = esp_ble_gatts_register_callback(gatts_event_handler);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret);
return;
}
ret = esp_ble_gap_register_callback(gap_event_handler);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret);
return;
}
ret = esp_ble_gatts_app_register(ESP_APP_ID);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "gatts app register error, error code = %x", ret);
return;
}
esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);
if (local_mtu_ret){
ESP_LOGE(GATTS_TABLE_TAG, "set local MTU failed, error code = %x", local_mtu_ret);
}
}
/*
* 20
* [0] #
* [1]
* [2] 0
* ...
*/
static uint16_t gatts_mtu_size = 23;
void ble_write_data(int id, uint8_t *data, int len)
{
// ESP_LOGI(GATTS_TABLE_TAG, "ble_write_data %d:", len);
// esp_log_buffer_hex(GATTS_TABLE_TAG, data, len);
if (len <= gatts_mtu_size - 3) /* 包数据可以一次完整发送 */
{
esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id], len, data, false);
}
else /* 需要分包发送 */
{
int total_num = 0;
uint8_t buf[gatts_mtu_size - 3];
if ((len % (gatts_mtu_size - 6)) == 0){
total_num = len / (gatts_mtu_size - 6);
}
else{
total_num = len / (gatts_mtu_size - 6) + 1;
}
// ESP_LOGI(GATTS_TABLE_TAG, "notify packet has %d", total_num);
int i = 0;
buf[0] = '#';
buf[1] = total_num;
for (i = 0; i < total_num - 1; i++)
{
buf[2] = i;
memcpy(buf + 3, data + i * (gatts_mtu_size - 6), gatts_mtu_size - 6);
esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id],gatts_mtu_size - 3, buf, false);
}
/* 最后一个包 */
buf[2] = i;
memcpy(buf + 3, data + i * (gatts_mtu_size - 6), len % (gatts_mtu_size - 6));
esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id], (len % (gatts_mtu_size - 6)) + 3, buf, false);
// ESP_LOGI(GATTS_TABLE_TAG, "notify packet send end!");
}
}
// 注意,该函数不是线程安全了,因为假设包是按顺序接受的,无法同时处理多个包的交替发送
void ble_read_data(uint8_t *data, int len)
{
ESP_LOGI(GATTS_TABLE_TAG, "ble_read_data");
static uint8_t buf[1024]; // 注意,这里大小没处理
static int buflen = 0;
static int total_num = 0;
static int next_packet_id = 0;
uint8_t *txbuf = NULL;
int txlen = 0;
if (len <= 0) return;
if (data[0] == '#') // 分包数据
{
if (len < 3) return;
if ((buflen != 0 && data[1] != total_num) || data[2] != next_packet_id) // 包错误,全部丢弃
{
ESP_LOGE(GATTS_TABLE_TAG, "ble packet err!");
buflen = 0;
next_packet_id = 0;
return;
}
if (buflen == 0) total_num = data[1];
memcpy(buf + buflen, data + 3, len - 3);
buflen += len - 3;
next_packet_id++;
if (next_packet_id == data[1]) // 接收完成
{
ESP_LOGI(GATTS_TABLE_TAG, "ble paclet recoved ok, all %d packets!", next_packet_id);
esp_log_buffer_hex(GATTS_TABLE_TAG, buf, buflen);
pad_deal_recived_data(buf, buflen, &data_notify_enable, &txbuf, &txlen);
if (txbuf != NULL)
{
ble_write_data(IDX_DATA_READ_WRITE_VAL, txbuf, txlen);
free(txbuf);
}
buflen = 0;
next_packet_id = 0;
}
}
else // 不分包的数据
{
esp_log_buffer_hex(GATTS_TABLE_TAG, data, len);
pad_deal_recived_data(data, len, &data_notify_enable, &txbuf, &txlen);
if (txbuf != NULL)
{
ble_write_data(IDX_DATA_READ_WRITE_VAL, txbuf, txlen);
free(txbuf);
}
}
}
void ble_server_notify(uint8_t *data, int len)
{
if (data_notify_enable && is_connected)
{
ble_write_data(IDX_DATA_NOTIFY_VAL, data, len);
}
}

View File

@ -0,0 +1,170 @@
// 与pad之间进行数据通信具有蓝牙、wifi两种方式
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "inc/communication_pad.h"
#include "inc/wifi_softap.h"
#include "inc/udp_server.h"
#include "inc/ble_gatts_server.h"
#include "../stm32/ModbusS.h"
#include "../stm32/config.h"
static const char *TAG = "communication_pad";
padDataCtrl_t pad_notify_data;
struct measureData measure_data;
int register_pad_data(padDataCtrl_t *data_ctrl, uint8_t tag, uint8_t *data, int len, padUpdataFun updata_fun)
{
if (data_ctrl->cnt >= MAX_NOTIFY_DATA)
{
ESP_LOGI(TAG, "register_pad_data failed, data_ctrl is full");
return -1;
}
data_ctrl->datas[data_ctrl->cnt].tag = tag;
data_ctrl->datas[data_ctrl->cnt].data = data;
data_ctrl->datas[data_ctrl->cnt].len = len;
data_ctrl->datas[data_ctrl->cnt].updata_fun = updata_fun;
data_ctrl->cnt++;
return 0;
}
extern flow_t *pflow;
extern depth_t *depth_data;
static void measure_data_updata(void)
{
measure_data.speed = depth_data->speed;
measure_data.time = depth_data->one_pile_work_time;
measure_data.depth = depth_data->depth;
measure_data.pile_id = gWordVar[LAST_PILE_ID_ADDR];
measure_data.flow1 = pflow[0].flow;
measure_data.flow_10cm1 = depth_data->depth_flow[0];
measure_data.flow_total1 = pflow[0].total_flow;
measure_data.flow2 = pflow[1].flow;
measure_data.flow_10cm2 = depth_data->depth_flow[1];
measure_data.flow_total2 = pflow[1].total_flow;
measure_data.current[0] = gWordVar[AC_CURRENT_REG_ADDR + 0];
measure_data.current[1] = gWordVar[AC_CURRENT_REG_ADDR + 1];
measure_data.current[2] = gWordVar[AC_CURRENT_REG_ADDR + 2];
}
extern gps_message_t *gps_message;
// 上报data_ctrl中的数据
static void pad_notify_data_fun(const padDataCtrl_t *data_ctrl)
{
uint8_t data[1024]; // 这里的大小并没有控制
int data_len =0;
// data[0] = NOTIFY_TAG;
// data_len = 1;
for (int i = 0; i < data_ctrl->cnt; i++)
{
if (data_ctrl->datas[i].updata_fun) data_ctrl->datas[i].updata_fun(); // 更新数据
data[data_len++] = data_ctrl->datas[i].tag;
data[data_len++] = data_ctrl->datas[i].len;
memcpy(data + data_len, data_ctrl->datas[i].data, data_ctrl->datas[i].len);
data_len += data_ctrl->datas[i].len;
}
// ESP_LOGI(TAG, "gps message: %f, %f", gps_message->x, gps_message->y);
// 调用蓝牙和wifi的notify函数
udp_server_notify(data, data_len);
ble_server_notify(data, data_len);
}
static void pad_notify_task(void *pvParameters)
{
ESP_LOGI(TAG, "pad_notify_task");
while (1)
{
pad_notify_data_fun(&pad_notify_data);
vTaskDelay(pdMS_TO_TICKS(200));
}
vTaskDelete(NULL);
}
// 通信初始化
void pad_communication_init(void)
{
wifi_init_softap();
udp_server_init();
ble_gatts_server_init();
register_pad_data(&pad_notify_data, 0xA1, &measure_data, sizeof(measure_data), measure_data_updata);
register_pad_data(&pad_notify_data, 0xA2, &gWordVar[REG_GPS_MESSAGE], sizeof(gps_message_t), NULL); // 透传不用更新数据
xTaskCreate(pad_notify_task, "pad_notify_task", 4096, NULL, 8, NULL);
}
/*
* :
* 1byte + ...
* 0XF0: 2byte寄存器地址 + 1byte数据长度 +
* 0XF1: 2byte寄存器地址 + 1byte数据长度
* 0XF2:notify
* 0XF3:notify
* NULLfree
*/
void pad_deal_recived_data(uint8_t *data, int len, int *enable_notify, uint8_t **retbuf, int *retlen)
{
ESP_LOGI(TAG, "pad_deal_recived_data");
*retbuf = NULL;
*retlen = 0;
if (len >= 4 && data[0] == 0xF0) /* 写gWordVar寄存器 */
{
uint16_t addr = data[1] + (data[2] << 8);
uint16_t addr_ = addr;
uint8_t cnt = data[3];
if (cnt > len - 4)
{
ESP_LOGI(TAG, "write format is fault, cnt > len - 4");
return;
}
ESP_LOGI(TAG, "write addr:%d cnt:%d", addr, cnt);
uint8_t i;
for (i = 0 + 4; i < cnt + 4; i+=2) /* 发送的数据要求两字节对齐 */
{
gWordVar[addr++] = data[i] + (data[i + 1] << 8);
ESP_LOGI(TAG, "gwordvar[%d]:0x%x", addr-1, gWordVar[addr-1]);
}
ModBusWordWriteHook(addr_, cnt);
}
else if (len >= 4 && data[0] == 0xF1) /* 读gWordVar返回*/
{
uint16_t addr = data[1] + (data[2] << 8);
uint8_t cnt = data[3];
ESP_LOGI(TAG, "read addr:%d cnt:%d", addr, cnt);
*retbuf = (uint8_t *)malloc(cnt + 4);
(*retbuf)[0] = data[0];
(*retbuf)[1] = data[1];
(*retbuf)[2] = data[2];
(*retbuf)[3] = data[3];
memcpy((*retbuf) + 4, (uint8_t *)(gWordVar + addr), cnt);
*retlen = cnt + 4;
}
else if (len == 1 && data[0] == 0xF2) /* 开启notify */
{
ESP_LOGI(TAG, "enable notify");
*enable_notify = 1;
}
else if (len == 1 && data[0] == 0xF3) /* 关闭notify */
{
ESP_LOGI(TAG, "disable notify");
*enable_notify = 0;
}
else ESP_LOGI(TAG, "format err!");
}

View File

@ -0,0 +1,32 @@
#ifndef __BLE_GATTS_SERVER_H
#define __BLE_GATTS_SERVER_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/* Attributes State Machine */
enum
{
IDX_SVC,
/* gWordVar data write */
IDX_DATA_READ_WRITE_CHAR,
IDX_DATA_READ_WRITE_VAL,
IDX_DATA_READ_WRITE_CFG,
/* gWordVar data notify */
IDX_DATA_NOTIFY_CHAR,
IDX_DATA_NOTIFY_VAL,
IDX_DATA_NOTIFY_CFG,
IDX_NB,
};
void ble_gatts_server_init(void);
void ble_write_data(int id, uint8_t *data, int len);
void ble_read_data(uint8_t *data, int len);
void ble_server_notify(uint8_t *data, int len);
#endif

View File

@ -0,0 +1,63 @@
#ifndef __COMMUNICATION_PAD_H
#define __COMMUNICATION_PAD_H
#include <stdint.h>
#define MAX_NOTIFY_DATA 20
#define NOTIFY_TAG 0xF2
struct measureData // 测量数据
{
int16_t speed;
uint16_t time;
int16_t depth;
uint16_t pile_id;
int16_t flow1;
uint16_t flow_10cm1;
int32_t flow_total1;
int16_t flow2;
uint16_t flow_10cm2;
int32_t flow_total2;
uint16_t current[3];
};
typedef struct gps_message
{
uint8_t gps_status; // GPS定位状态
uint8_t gps_view; // GPS可视状态
uint8_t gps_use; // GPS使用状态
uint8_t reg[1]; // 保留
uint32_t utc; // utc时间
double x; // 大地平面坐标
double y;
double dir; // 方向
double pitch; // 俯仰角
} gps_message_t;
typedef void (*padUpdataFun)(void);
typedef struct padDataStruct
{
uint8_t tag;
int len;
uint8_t *data;
padUpdataFun updata_fun;
} padData_t;
typedef struct padDataCtrlStruct
{
int cnt;
padData_t datas[MAX_NOTIFY_DATA]; // 输出数据,即上报数据
} padDataCtrl_t;
void pad_communication_init(void);
int register_pad_data(padDataCtrl_t *data_ctrl, uint8_t tag, uint8_t *data, int len, padUpdataFun updata_fun);
void pad_deal_recived_data(uint8_t *data, int len, int *enable_notify, uint8_t **retbuf, int *ret_len);
#endif

View File

@ -0,0 +1,23 @@
#ifndef __TCP_SERVER_H
#define __TCP_SERVER_H
#include <stdint.h>
#define TCP_SERVER_PORT 6000
// 链表,记录连接的客户端
struct clientNode
{
struct tcp_pcb *pcb;
int enable_notify; // 是否使能数据上报
struct clientNode *next;
};
void tcp_server_init(void);
void ble_write_data(int id, uint8_t *data, int len);
void ble_read_data(uint8_t *data, int len);
void tcp_server_notify(uint8_t *data, int len);
#endif

View File

@ -0,0 +1,23 @@
#ifndef __UDP_SERVER_H
#define __UDP_SERVER_H
#include <stdint.h>
#include "lwip/ip_addr.h"
#define UDP_SERVER_PORT 6000
#define UDP_NOTIFY_TIMEOUT (60 * 5) // 200ms notify一次5s超时
// 链表,记录连接的客户端
struct clientNode
{
struct udp_pcb *upcb;
ip_addr_t addr;
uint16_t port;
int notify_timeout; // 上报数据的超时时间,客户端需定期发送上报请求
struct clientNode *next;
};
void udp_server_init(void);
void udp_server_notify(uint8_t *data, int len);
#endif

View File

@ -0,0 +1,6 @@
#ifndef __WIFI_SOFTAP_H
#define __WIFI_SOFTAP_H
void wifi_init_softap(void);
#endif

View File

@ -0,0 +1,170 @@
#include <stdint.h>
#include <string.h>
#include "lwip/ip_addr.h"
#include "lwip/tcp.h"
#include "lwip/err.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "esp_log.h"
#include "tcp_server.h"
#include "inc/communication_pad.h"
#define LOG_TAG "[communication_tcp_sr]: "
struct clientNode client_list; // 客户端链表头结点
struct clientNode *client_r_p = &client_list; // 客户端链表尾指针
void client_list_add(struct tcp_pcb *pcb)
{
struct clientNode *client = (struct clientNode *)malloc(sizeof(struct clientNode));
client->pcb = pcb;
client->enable_notify = 0;
client->next = NULL;
client_r_p->next = client;
client_r_p = client;
}
void client_list_delete(struct tcp_pcb *pcb)
{
struct clientNode *p = &client_list;
while (p->next)
{
if (p->next->pcb == pcb)
{
struct clientNode *q = p->next;
if (q == client_r_p)
{
client_r_p = p;
}
p->next = q->next;
free(q);
return;
}
p = p->next;
}
}
void cilent_list_delete_all(void)
{
struct clientNode *p = &client_list;
while (p->next)
{
struct clientNode *q = p->next;
p->next = q->next;
free(q);
}
client_r_p = &client_list;
}
struct clientNode* find_client_by_pcb(struct tcp_pcb *pcb)
{
struct clientNode *p = client_list.next;
struct clientNode *ret = NULL;
while (p)
{
if (p->pcb == pcb)
{
ret = p;
break;
}
p = p->next;
}
return ret;
}
static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) {
if (p != NULL) {
uint8_t *rxbuf;
uint8_t *txbuf = NULL;
int rxlen, txlen = 0;
tcp_recved(newpcb, p->tot_len);
rxbuf = (uint8_t *)p->payload;
rxlen = p->len;
ESP_LOGI(LOG_TAG, "recive data %d:", rxlen);
esp_log_buffer_hex(LOG_TAG, rxbuf, rxlen);
// 接受到数据调用pad_deal_recived_data处理如果需要回复读操作则再将数据发送出去
struct clientNode* client = find_client_by_pcb(newpcb);
if (!client)
{
ESP_LOGI(LOG_TAG, "err:not find this client");
return ERR_OK;
}
pad_deal_recived_data(rxbuf, rxlen, &client->enable_notify, &txbuf, &txlen);
if (txbuf)
{
tcp_write(newpcb, txbuf, txlen, 1);
free(txbuf);
}
pbuf_free(p);
}
else if (err == ERR_OK)
{
ESP_LOGI(LOG_TAG, "gps1 remote end is closing the connection\n");
tcp_err(newpcb, NULL);
tcp_recv(newpcb, NULL);
// tcp_poll(newpcb, NULL, 120);
err_t err_p = tcp_close(newpcb);
client_list_delete(newpcb);
if (ERR_OK != err_p)
{
ESP_LOGI(LOG_TAG, "gps1 close error. err:%d\n", err_p);
}
return err_p;
}
return ERR_OK;
}
static void ModBusSlave_conn_err(void *arg, err_t err) {
ESP_LOGI(LOG_TAG, "connect err!");
// log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err);
// cilent_list_delete_all(); // 不知道为什么这个回调函数没有提供newpcb
}
static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) {
// if (newpcb) {
// // log_printf(LERROR, LOG_TAG "close pcb\n");
// tcp_close(newpcb);
// newpcb = NULL;
// }
ESP_LOGI(LOG_TAG, "poll!");
return ERR_OK;
}
static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
ESP_LOGI(LOG_TAG, "TCP accept 0x%x", (unsigned int)pcb);
tcp_err(pcb, ModBusSlave_conn_err);
tcp_recv(pcb, ModBusSlave_recv);
// tcp_poll(pcb, ModBusSlave_poll, 120); // 60 second timeout
client_list_add(pcb);
return ERR_OK;
}
void tcp_server_init(void) {
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, TCP_SERVER_PORT);
pcb = tcp_listen(pcb);
tcp_accept(pcb, ModBusSlave_accept);
}
// 遍历所有客户端,如果允许上报,则将数据上报
void tcp_server_notify(uint8_t *data, int len)
{
struct clientNode *p = client_list.next;
while (p)
{
if (p->enable_notify == 1) // 开启上报
{
// ESP_LOGI(LOG_TAG, "tcp_server_notify");
// esp_log_buffer_hex(LOG_TAG, data, len);
tcp_write(p->pcb, data, len, 1);
tcp_output(p->pcb);
}
p = p->next;
}
}

View File

@ -0,0 +1,169 @@
#include <stdint.h>
#include <string.h>
#include "lwip/ip_addr.h"
#include "lwip/udp.h"
#include "lwip/err.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "esp_log.h"
#include "inc/udp_server.h"
#include "inc/communication_pad.h"
#define LOG_TAG "[communication_udp_server]: "
struct clientNode client_list; // 客户端链表头结点
struct clientNode *client_r_p = &client_list; // 客户端链表尾指针
struct clientNode *client_list_add(struct udp_pcb * upcb, ip_addr_t *addr, uint16_t port)
{
struct clientNode *p = client_list.next;
struct clientNode *ret = NULL;
while (p)
{
if (ip_addr_cmp(&p->addr, addr) && p->port == port)
{
ret = p;
break;
}
p = p->next;
}
if (ret == NULL)
{
struct clientNode *client = (struct clientNode *)malloc(sizeof(struct clientNode));
client->upcb = upcb;
ip_addr_copy(client->addr, *addr);
client->port = port;
client->notify_timeout = UDP_NOTIFY_TIMEOUT;
client->next = NULL;
client_r_p->next = client;
client_r_p = client;
ret = client;
}
return ret;
}
// 返回删除的前一个
struct clientNode *client_list_delete(ip_addr_t *addr, uint16_t port)
{
struct clientNode *p = &client_list;
while (p->next)
{
if (ip_addr_cmp(&p->next->addr, addr) && p->next->port == port)
{
struct clientNode *q = p->next;
if (q == client_r_p)
{
client_r_p = p;
}
p->next = q->next;
free(q);
return p;
}
p = p->next;
}
return NULL;
}
void cilent_list_delete_all(void)
{
struct clientNode *p = &client_list;
while (p->next)
{
struct clientNode *q = p->next;
p->next = q->next;
free(q);
}
client_r_p = &client_list;
}
void udp_server_recived(void *arg, struct udp_pcb *upcb, struct pbuf *pkt_buf,
ip_addr_t *addr, u16_t port)
{
uint8_t *rxbuf;
uint8_t *txbuf = NULL;
int rxlen, txlen = 0;
rxbuf = (uint8_t *)pkt_buf->payload;
rxlen = pkt_buf->len;
ESP_LOGI(LOG_TAG, "recive data %d:", rxlen);
esp_log_buffer_hex(LOG_TAG, rxbuf, rxlen);
// 接受到数据调用pad_deal_recived_data处理如果需要回复读操作则再将数据发送出去
struct clientNode* client = client_list_add(upcb, addr, port);
int enable_notify = -1;
pad_deal_recived_data(rxbuf, rxlen, &enable_notify, &txbuf, &txlen);
if (enable_notify == 1)
{
client->notify_timeout = UDP_NOTIFY_TIMEOUT;
}
else if (enable_notify == 0)
{
client->notify_timeout = 0;
}
if (txbuf)
{
struct pbuf *pkt_txbuf = pbuf_alloc(PBUF_TRANSPORT, 1400, PBUF_RAM);
char *buf = (char *)pkt_txbuf->payload;
pkt_txbuf->len = txlen;
pkt_txbuf->tot_len = txlen;
memcpy(buf, txbuf, txlen);
err_t err = udp_sendto(upcb, pkt_txbuf, &addr, port);
pbuf_free(pkt_txbuf);
free(txbuf);
}
pbuf_free(pkt_buf);
}
void udp_server_init(void) {
err_t err;
struct udp_pcb *UDPpcb;
UDPpcb = udp_new();
if (!UDPpcb)
{
return;
}
err = udp_bind(UDPpcb, IP_ADDR_ANY, UDP_SERVER_PORT);
if (err != ERR_OK)
{
return;
}
udp_recv(UDPpcb, udp_server_recived, NULL);
}
// 遍历所有客户端,如果允许上报,则将数据上报
void udp_server_notify(uint8_t *data, int len)
{
struct clientNode *p = client_list.next;
while (p)
{
if (p->notify_timeout > 0)
{
// ESP_LOGI(LOG_TAG, "tcp_server_notify");
// esp_log_buffer_hex(LOG_TAG, data, len);
struct pbuf *pkt_txbuf = pbuf_alloc(PBUF_TRANSPORT, 1400, PBUF_RAM);
char *buf = (char *)pkt_txbuf->payload;
pkt_txbuf->len = len;
pkt_txbuf->tot_len = len;
memcpy(buf, data, len);
udp_sendto(p->upcb, pkt_txbuf, &p->addr, p->port);
pbuf_free(pkt_txbuf);
p->notify_timeout--;
}
else if (p->notify_timeout == 0) // 时间耗尽,删除
{
p = client_list_delete(&p->addr, p->port);
if (p == NULL)
{
ESP_LOGI(LOG_TAG, "err, confilct");
return;
}
}
p = p->next;
}
}

View File

@ -0,0 +1,99 @@
#include <string.h>
#include "wifi_softap.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
// #include "esp_system.h"
// #include "../../../components/esp_wifi/include/esp_wifi.h"
// #include "../../../components/esp_hw_support/include/esp_mac.h"
#define ESP_WIFI_SSID "T2N_056455"
#define ESP_WIFI_PASS "01010101"
#define ESP_WIFI_CHANNEL 1
#define MAX_STA_CONN 8
static const char *TAG = "wifi softAP";
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
void wifi_init_softap(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = ESP_WIFI_SSID,
.ssid_len = strlen(ESP_WIFI_SSID),
.channel = ESP_WIFI_CHANNEL,
.password = ESP_WIFI_PASS,
.max_connection = MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK},
};
nvs_handle_t my_handle;
esp_err_t err = nvs_open("wifi", NVS_READWRITE, &my_handle);
if (err == ESP_OK)
{
size_t len;
char temp_str[64];
uint8_t channel;
if (nvs_get_str(my_handle, "ap_ssid", temp_str, &len) == ESP_OK)
{
strncpy((char*)wifi_config.ap.ssid, temp_str, len);
wifi_config.ap.ssid_len = len;
}
if (nvs_get_str(my_handle, "ap_psk", temp_str, &len) == ESP_OK)
{
strncpy((char*)wifi_config.ap.password, temp_str, len);
}
if (nvs_get_u8(my_handle, "ap_ch", &channel) == ESP_OK)
{
wifi_config.ap.channel = channel;
}
nvs_close(my_handle);
}
if (strlen(ESP_WIFI_PASS) == 0)
{
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL);
}

View File

@ -1,22 +1,112 @@
/* WiFi station Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h" #include "esp_system.h"
#include "nvs_flash.h" #include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#include "can_network.h"
#include "freertos/queue.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "driver/mcpwm.h"
#include "driver/uart.h"
/*蓝牙相关的头文件*/
// #include "esp_bt.h"
// #include "esp_gap_ble_api.h"
// #include "esp_gatts_api.h"
// #include "esp_bt_defs.h"
// #include "esp_bt_main.h"
//#include "ble_server.h"
#include "stm32/config.h"
#include "communication_pad.h"
#include "stm32/pile_id.h"
#include "stm32/led.h"
#include "config.h"
#include "uart0_modbus_slave.h" /* The examples use WiFi configuration that you can set via project configuration menu
#include "flow.h"
#include "bl0939.h" If you'd rather not, just change the below entries to strings with
#include "depth.h" the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif
/* FreeRTOS event group to signal when we are connected*/
//static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define GPIO_4G_PWR GPIO_NUM_4
#define PWR_4G_ON (0)
#define PWR_4G_OFF (1)
static const char *TAG = "main"; static const char *TAG = "main";
//static int s_retry_num = 0;
// extern void wifi_init_softap(void);
void PWR_4G_Init(void);
extern void can_init(void);
extern void FLOW_init();
extern void DEPTH_init();
extern void BL0939_init(void);
extern void ads1220_task_start(void);
extern void ModBusTCPSlave_init(void);
extern esp_err_t i2c_master_init(void);
extern void config_load(void);
extern void uart0_modbus_slave_init(void);
extern void bt_client_init(void);
// extern void communication_tcp_init(void);
//extern void ESP32_Uart_Receive_Data(void);
uint32_t rtc_clk_apb_freq; uint32_t rtc_clk_apb_freq;
extern void pcnt_rotary_encoder_init_(void); extern uint16_t *cur_pile_id;
extern cal_4_20ma_t *cal_4_20ma;//电流数据结构体
extern flow_config_t *flow_config;//流量数据结构体
extern depth_config_t *depth_config;//深度数据结构体
void app_main(void) void app_main(void)
{ {
// Initialize NVS
esp_err_t ret = nvs_flash_init(); esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{ {
@ -24,12 +114,52 @@ void app_main(void)
ret = nvs_flash_init(); ret = nvs_flash_init();
} }
ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(i2c_master_init());
//restore_default();
// *cur_pile_id = 0;
// save_pile_id();
config_load();//读取保存在FRAM里的数据
// rtc_clk_apb_freq = rtc_clk_apb_freq_get();
// ESP_LOGI(TAG, "rtc_clk_apb_freq=%u", rtc_clk_apb_freq);
// can_init();
// PWR_4G_Init();
led_init();
ads1220_task_start(); /* 两路电流AD采样获取瞬时流量计算累计流量目前配置的是10HZ取决于SPS */
BL0939_init(); /* 实时采集通道电流根据depth_config_t中配置的启动与结束电流以及持续时间进行move_t机器开关状态的判断 */
DEPTH_init(); /* 编码器计算深度同时进行流量的按深度计数以及record的记录 */
// FLOW_init(); /* 两一种计算流量的方法,计算累计流量 */
pile_id_init();
config_init();
uart0_modbus_slave_init(); uart0_modbus_slave_init();
flow_init(); pad_communication_init();
BL0939_init(); //ESP32_Uart_Receive_Data();
// pcnt_rotary_encoder_init_();
DEPTH_init();
} }
void PWR_4G_Init(void)
{
ESP_LOGI(TAG, "HELLO~");
save_cal_4_20ma();
// zero-initialize the config structure.
gpio_config_t io_conf = {
// disable interrupt
.intr_type = GPIO_INTR_DISABLE,
// set as output mode
.mode = GPIO_MODE_OUTPUT,
// bit mask of the pins that you want to set,e.g.GPIO18/19
.pin_bit_mask = GPIO_4G_PWR,
// disable pull-down mode
.pull_down_en = 0,
// disable pull-up mode
.pull_up_en = 0,
};
// configure GPIO with the given settings
gpio_config(&io_conf);
gpio_set_level(GPIO_4G_PWR, PWR_4G_OFF);
vTaskDelay(pdMS_TO_TICKS(1000));
gpio_set_level(GPIO_4G_PWR, PWR_4G_ON);
}

140
main/modbus-tcp.c Normal file
View File

@ -0,0 +1,140 @@
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <string.h>
#include "lwip/ip_addr.h"
#include "lwip/tcp.h"
#include "lwip/err.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "stm32/ModbusS.h"
#include "esp_log.h"
// #include "log.h"
#define LOG_TAG "[mb_tcp_sr]: "
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
// static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
// static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err);
// static void ModBusSlave_conn_err(void *arg, err_t err);
// static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *pcb);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Called when a data is received on the telnet connection
* @param arg the user argument
* @param pcb the tcp_pcb that has received the data
* @param p the packet buffer
* @param err the error value linked with the received data
* @retval error value
*/
int ModBusTcpMonitor;
static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) {
/* We perform here any necessary processing on the pbuf */
if (p != NULL) {
uint8_t *txbuf;
uint8_t *rxbuf;
int txlen, rxlen;
/* We call this function to tell the LwIp that we have processed the data */
/* This lets the stack advertise a larger window, so more data can be received*/
tcp_recved(newpcb, p->tot_len);
rxbuf = (uint8_t *)p->payload;
rxlen = p->len;
if (rxlen < 6) {
pbuf_free(p);
return tcp_close(newpcb);
}
txbuf = (uint8_t *)mem_malloc(1024 + 16);
if (txbuf == NULL) {
return tcp_close(newpcb);
}
ModBusTcpMonitor = 0;
txlen = ModbusSlaveProcess(&txbuf[6], &rxbuf[6], (rxlen - 6), 0); //以前有 2023年4月24日14:39:11
// log_printf(LINFO, LOG_TAG "[%s] ModbusSlaveProcess (ret=%d)", __FUNCTION__, txlen);
if (txlen > 0) {
int i;
for (i = 0; i < 4; i++) {
txbuf[i] = rxbuf[i];
}
txbuf[4] = (uint8_t)(txlen >> 8);
txbuf[5] = (uint8_t)(txlen & 0xff);
tcp_write(newpcb, txbuf, txlen + 6, 1);
ModBusTcpMonitor = 0;
}
mem_free(txbuf);
/* End of processing, we free the pbuf */
pbuf_free(p);
} else if (err == ERR_OK) {
/* When the pbuf is NULL and the err is ERR_OK, the remote end is closing the connection. */
/* We free the allocated memory and we close the connection */
// log_printf(LWARN, LOG_TAG "remote end is closing the connection\n");
tcp_err(newpcb, NULL);
tcp_recv(newpcb, NULL);
tcp_poll(newpcb, NULL, 120); // 60 second timeout
// return tcp_close(newpcb);
err_t err_p = tcp_close(newpcb);
if (ERR_OK != err_p) {
// log_printf(LERROR, LOG_TAG "close error. err:%d\n", err_p);
}
return err_p;
}
return ERR_OK;
}
/**
* @brief This function is called when an error occurs on the connection
* @param arg
* @parm err
* @retval None
*/
static void ModBusSlave_conn_err(void *arg, err_t err) {
// log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err);
}
static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) {
// if (newpcb) {
// // log_printf(LERROR, LOG_TAG "close pcb\n");
// tcp_close(newpcb);
// newpcb = NULL;
// }
ESP_LOGI(LOG_TAG, "HELLO!");
return ERR_OK;
}
/**
* @brief This function when the Telnet connection is established
* @param arg user supplied argument
* @param pcb the tcp_pcb which accepted the connection
* @param err error value
* @retval ERR_OK
*/
static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
/* Tell LwIP to associate this structure with this connection. */
// tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));
/* Configure LwIP to use our call back functions. */
tcp_err(pcb, ModBusSlave_conn_err);
tcp_recv(pcb, ModBusSlave_recv);
tcp_poll(pcb, ModBusSlave_poll, 1); // 60 second timeout
/* Send out the first message */
// tcp_write(pcb, GREETING, strlen(GREETING), 1);
return ERR_OK;
}
/**
* @brief Initialize the hello application
* @param None
* @retval None
*/
void ModBusTCPSlave_init(void) {
struct tcp_pcb *pcb;
/* Create a new TCP control block */
pcb = tcp_new();
/* Assign to the new pcb a local IP address and a port number */
/* Using IP_ADDR_ANY allow the pcb to be used by any local interface */
tcp_bind(pcb, IP_ADDR_ANY, 502);
/* Set the connection to the LISTEN state */
pcb = tcp_listen(pcb);
/* Specify the function to be called when a connection is established */
tcp_accept(pcb, ModBusSlave_accept);
// LSAPI_Log_Debug("ModBus Tcp server listen port:%d\n", 502);
}
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

27
main/modbus-tcp.h Normal file
View File

@ -0,0 +1,27 @@
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HELLOWERLOD_H
#define __HELLOWERLOD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/** @defgroup helloworld_Exported_Functions
* @{
*/
void HelloWorld_init(void);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __HELLOWERLOD_H */
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

View File

@ -1,25 +0,0 @@
#ifndef _MODBUS_H
#define _MODBUS_H
#include <stdint.h>
#include "gwordvar.h"
#define setBit(Add) gBitVar[(Add)>>3] |= (1<<((Add)&0x07))
#define clrBit(Add) gBitVar[(Add)>>3] &= ~(1<<((Add)&0x07))
#define BUFFER_SIZE 2000
#define gBIT_SIZE 128
#define MODBUS_SALVE_ADDRESS 0x01
extern uint8_t gBitVar[(gBIT_SIZE+7)/8];
extern uint8_t rx_buffer[256];
extern uint8_t tx_buffer[256];
extern uint16_t rx_buff_len;
extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc);
void ModBusWordWriteHook(uint16_t addr, uint16_t length);
#endif

View File

@ -1,29 +0,0 @@
#ifndef __GWORDVAR_H
#define __GWORDVAR_H
#include <stdint.h>
#include "flow.h"
#define FLOW_REG_ADDR 0
#define DEPTH_REG_ADDR 12
#define AC_CURRENT_REG_ADDR 24
#define MOVE_REG_ADDR 27
#define TILT_SENSER_ADDR 30
#define RECORD_REG_ADDR 32
#define CAL_4_20MA_ADDR 384
#define FLOW_CONFIG_ADDR (CAL_4_20MA_ADDR + (sizeof(cal_4_20ma_t) + 15) / 16 * 8)
#define DEPTH_CONFIG_ADDR (FLOW_CONFIG_ADDR + (sizeof(flow_config_t) + 15) / 16 * 8)
#define AD_RAW_REG_ADDR 444
#define LAST_PILE_ID_ADDR 509
#define DEPTH_RESET_ADDR 510
#define REBOOT_REW_ADDR 511
#define REG_GPS_MESSAGE (512 + 48)
#define REG_GPS_WRITE_DATA (REG_GPS_MESSAGE + sizeof(gps_message_t))
#define gWORD_SIZE 1024
extern uint16_t gWordVar[gWORD_SIZE];
#endif

View File

@ -1,11 +0,0 @@
#ifndef __UART0_MODBUS_SLAVE_H
#define __UART0_MODBUS_SLAVE_H
#define UART_PORT_NUM (0)
#define BAUD_RATE (460800)
#define BUF_SIZE (256)
#define UART_READ_TOUT (50 / portTICK_PERIOD_MS)
void uart0_modbus_slave_init(void);
#endif

View File

@ -1,82 +0,0 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "uart0_modbus_slave.h"
#include "ModbusS.h"
#include "led.h"
static const char *TAG = "UART0";
uint8_t txbuf[BUF_SIZE];
uint8_t rxbuf[BUF_SIZE];
extern uint16_t gWordVar[];
void uart0_init(void)
{
const int uart_num = UART_PORT_NUM;
uart_config_t uart_config = {
.baud_rate = BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
.source_clk = UART_SCLK_APB,
};
// Set UART log level
// esp_log_level_set(TAG, ESP_LOG_NONE);
ESP_LOGI(TAG, "Start RS485 application test and configure UART.");
// Install UART driver (we don't need an event queue here)
// In this example we don't even use a buffer for sending data.
ESP_ERROR_CHECK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE, 0, NULL, 0));
// Configure UART parameters
ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
ESP_LOGI(TAG, "UART set pins, mode and install driver.");
// Set UART pins as per KConfig settings
//ESP_ERROR_CHECK(uart_set_pin(uart_num, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));之前没解开注释
//ESP_ERROR_CHECK(uart_set_pin(uart_num, 11, 13, 12, -1));
// Set RS485 half duplex mode
ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX));
// Set read timeout of UART TOUT feature
ESP_ERROR_CHECK(uart_set_rx_timeout(uart_num, UART_READ_TOUT));
}
void uart0_modbus_slave_task(void *arg)
{
ESP_LOGI(TAG, "uart0_modbus_slave_task");
while (1)
{
int txlen = 0;
int len = uart_read_bytes(UART_PORT_NUM, rxbuf, BUF_SIZE, UART_READ_TOUT);
// xTaskGetTickCount();
// ESP_LOGI("modbus_slave","-----------------------------rxlen:%d", len);
// for (int i = 0; i < len; i++)
// ESP_LOGI("modbus_slave","uart0 get: 0x%x", rxbuf[i]);
if (len > 0)
{
txlen = ModbusSlaveProcess(txbuf, rxbuf, len, 1);
// if (txlen > 0)
// {
// LED_Toggle(LED1_GPIO_PIN);
// int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, txlen);
// ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length);
// for (int i = 0; i < uart_write_length; i++)
// ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]);
// }
}
}
}
void uart0_modbus_slave_init(void)
{
uart0_init();
xTaskCreate(uart0_modbus_slave_task, "uart0_modbus_slave_task", 4096, NULL, 10, NULL);
}

View File

@ -1,19 +0,0 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#define MAGIC 30627
#define EE_CAL_4_20MA_ADDR 16
#define EE_FLOW_CFG_ADDR (EE_CAL_4_20MA_ADDR + sizeof(default_cal_4_20ma))
#define EE_DEPTH_CFG_ADDR (EE_FLOW_CFG_ADDR + sizeof(default_flow_cfg))
void config_init(void);
void config_load(void);
void restore_default(void);
void save_cal_4_20ma(void);
void save_flow_cfg(void);
void save_depth_cfg(void);
void save_pile_id(void);
#endif

View File

@ -1,24 +0,0 @@
#ifndef __FRAM_H
#define __FRAM_H
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#define I2C_MASTER_SCL_IO 1 /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO 2 /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define WRITE_BIT I2C_MASTER_WRITE
#define ACK_CHECK_EN 0x1
esp_err_t i2c_master_init(void);
int fram_write(uint16_t addr, void * buf,uint32_t len);
int fram_read(uint16_t addr,void * buf,uint32_t len);
#endif

View File

@ -1,481 +0,0 @@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "driver/mcpwm.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "depth.h"
#include "rotary_encoder.h"
#include "gwordvar.h"
#include "flow.h"
#include "bl0939.h"
#include "utils.h"
static const char *TAG = "depth";
extern uint16_t last_pile_id;
int32_t enc1_value; // 捕获中更新的值
uint32_t enc1_update_time;
uint32_t _enc1_update_time;
uint32_t enc2_update_time;
uint32_t _enc2_update_time;
int32_t enc2_value;
extern rotary_encoder_t *encoder;
depth_config_t *depth_config = (depth_config_t *)&gWordVar[DEPTH_CONFIG_ADDR];
depth_t *depth_data = (depth_t *)&gWordVar[DEPTH_REG_ADDR];
record_t *record = (record_t *)&gWordVar[RECORD_REG_ADDR];
rotary_encoder_t *encoder = NULL; // 编码器测量深度参数
void pcnt_rotary_encoder_init(void)
{
// Rotary encoder underlying device is represented by a PCNT unit in this example
uint32_t pcnt_unit = 0;
int pulse_pin;
int ctrl_pin;
if (depth_config->port)
{
pulse_pin = DEPTH_PIN_ENC_A;
ctrl_pin = DEPTH_PIN_ENC_B;
}
else
{
pulse_pin = DEPTH_PIN_PULSE;
ctrl_pin = DEPTH_PIN_CTRL;
}
// Create rotary encoder instance
rotary_encoder_config_t config = ROTARY_ENCODER_DEFAULT_CONFIG((rotary_encoder_dev_t)pcnt_unit, pulse_pin, ctrl_pin);
config.flags = depth_config->input_type;
ESP_ERROR_CHECK(rotary_encoder_new_ec11(&config, &encoder));
// Filter out glitch (1us)
ESP_ERROR_CHECK(encoder->set_glitch_filter(encoder, 10));
// Start encoder
ESP_ERROR_CHECK(encoder->start(encoder));
}
/**
* @brief this is an ISR callback, we take action according to the captured edge
*/
static bool depth_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// 双边沿触发中断,只有一个边缘会更新值,所以只有在值发生变化时才更新时间
int value = encoder->get_counter_value(encoder);
if (value != enc1_value)
{
enc1_value = value;
enc1_update_time = edata->cap_value;
}
return false;
}
void capture_depth_init()
{
int pulse_pin;
if (depth_config->port)
{
pulse_pin = DEPTH_PIN_ENC_A;
}
else
{
pulse_pin = DEPTH_PIN_PULSE;
}
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, pulse_pin));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pullup_en(pulse_pin));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = depth_isr_handler, // 绑定深度中断处理函数
.user_data = NULL
};
if (depth_config->input_type > 1)
{
conf.cap_edge = MCPWM_BOTH_EDGE;
}
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, &conf));
ESP_LOGI(TAG, "capture_depth_init");
}
void depth_init(void)
{
// if (depth_config->input_type == 1)
// { // 电压型 方向+脉冲信号 使用比较器通道,IO口中断方式采集
// // GPIO_InitTypeDef GPIO_InitStruct = {0};
// // /*Configure GPIO pin : PtPin */
// // GPIO_InitStruct.Pin = ROLLER_DIR_Pin;
// // GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
// // GPIO_InitStruct.Pull = GPIO_PULLUP;
// // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct);
// // /*Configure GPIO pin : PtPin */
// // GPIO_InitStruct.Pin = ROLLER_CLK_Pin;
// // GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
// // GPIO_InitStruct.Pull = GPIO_PULLUP;
// // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct);
// }
// else if (depth_config->input_type == 2)
// { // 电压型 正交编码器 使用比较器通道,TIM1编码器通道采集
// MX_TIM1_Init();
// pcnt_rotary_encoder_init(); // 编码器初始化
// capture_depth_init();
// HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
// }
// else if (depth_config->input_type == 3)
// { // 开漏输出 正交编码器 使用光耦输入通道,TIM3编码器通道采集
// // MX_TIM3_Init();
// // HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
// }
depth_data->depth_offset = -depth_config->depth_offset;
depth_data->pile_work_state_and_direction = (PILE_STATE_STOP | PILE_DIR_NONE); // 默认不工作
}
enum
{
REST = -1,
STOP = 0,
DOWN = 1,
UP = 2,
};
int last_enc_value = 0;
uint32_t _enc_update_time;
uint32_t enc_update_time;
int last_sample_depth = 0;
int last_flow[2] = {0};
int16_t prev_depth = 0;
uint32_t prev_update_time = 0;
int16_t target_sample_depth = 0;
extern bool is_connected;
// extern uint16_t spp_handle_table[IDX_NB];
extern uint16_t spp_conn_id;
extern flow_t *pflow;
void calculate_depth_speed(int speed_enc_value)
{
static int speed_last_enc_value = -1;
static int64_t speed_last_time = -1;
int64_t speed_time = esp_timer_get_time();
if (speed_last_enc_value == -1) // 第一次,记录值,并不计算
{
goto exit;
}
depth_data->speed = (speed_enc_value - speed_last_enc_value) * depth_config->N / depth_config->M * 600000ll / (speed_time - speed_last_time);
// ESP_LOGI(TAG, "speed:%d", depth_data->speed);
exit:
speed_last_enc_value = speed_enc_value;
speed_last_time = speed_time;
}
/**
* _enc1_update_time 1
* enc1_update_time 1
* time_diff
* depth_config
* enc1_value 1
* prev_depth
*/
void depth_task(void *arg)
{
ESP_LOGI(TAG, "depth_task start\n");
int time_diff = 0;
int speed_calc_count = 0;
int enc_value = 0;
int64_t work_start_time = 0;
uint16_t last_work_state = 0;
depth_data->depth_offset = -depth_config->depth_offset;
depth_data->pile_work_state_and_direction = 0x0300;
last_work_state = depth_data->pile_work_state_and_direction;
record->pile_id = ++last_pile_id;
gWordVar[LAST_PILE_ID_ADDR] = last_pile_id;
while (1)
{
if (_enc1_update_time != enc1_update_time) /* 深度数据更新 */
{
enc_update_time = enc1_update_time;
enc_value = enc1_value;
time_diff = abs_sub_uint32(enc_update_time, _enc1_update_time);
_enc1_update_time = enc_update_time;
}
//ESP_LOGI(TAG, "time_diff:%d", time_diff);
if (time_diff != 0)
{
// ESP_LOGI(TAG, "time_diff = %d\n",time_diff);
int16_t depth = enc_value * depth_config->N / depth_config->M; // 1mm
depth_data->depth = depth - depth_data->depth_offset;
/*深度补偿修正*/
if (depth_data->depth > depth_config->max_depth)
{
// ESP_LOGI(TAG, "depth_data->depth > depth_config->max_depth\n");
depth_data->depth_offset = depth - depth_config->max_depth;
depth_data->depth = depth_config->max_depth;
}
else if (depth_data->depth < depth_config->min_depth)
{
// ESP_LOGI(TAG, "depth_data->depth < depth_config->min_depth\n");
depth_data->depth_offset = depth - depth_config->min_depth;
depth_data->depth = depth_config->min_depth;
}
/*更新记录值*/
if (depth_data->depth > record->max_depth)
{
// ESP_LOGI(TAG, "depth_data->depth > record->max_depth\n");
record->max_depth = depth_data->depth;
// send_to_bt1.max_depth = depth_data->depth;
}
// ESP_LOGI(TAG, "depth_data->depth:0x%x", (unsigned int)depth_data->depth);
uint16_t pile_work_state = (depth_data->pile_work_state_and_direction & 0xff00);
if (pile_work_state == PILE_STATE_WORK)
{
// ESP_LOGI(TAG, "pile_work_state == PILE_STATE_WORK\n");
/*如果机器从停止状态->工作状态,则重新记录工作开始时间*/
if(last_work_state == PILE_STATE_STOP){
work_start_time = esp_timer_get_time();
depth_data->one_pile_work_time = 0;
}
int64_t current_work_time = esp_timer_get_time();
if(work_start_time != 0){
depth_data->one_pile_work_time = (uint16_t)((current_work_time - work_start_time)/1000000); // s
// ESP_LOGI(TAG, "time : %ud", (int)depth_data->one_pile_work_time);
}
/*下钻,深度增加 计算采样深度流量*/
if (enc_value > last_enc_value)
{
// ESP_LOGI(TAG, "enc_value > last_enc_value\n");
uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff);
if(pile_work_dir != PILE_DIR_DOWN)
{
// 方向改变,更新目标采样深度
depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_DOWN);
target_sample_depth = (depth_data->depth / depth_config->sample_depth) * depth_config->sample_depth;
// 小于半个采样长度的合并到下一个采样点
if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2)
{
target_sample_depth += depth_config->sample_depth;
}
}
// 到达或超过目标采样点
if (depth_data->depth >= target_sample_depth)
{
// 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点
// 当使用10线编码器时每个脉冲深度达6.25cm当采样间隔为10cm时抖动值太大
if ((prev_depth - depth_data->depth) != 0)
{
int i;
//uint32_t time = (target_sample_depth - prev_depth) * (enc_update_time - prev_update_time) / (depth_data->depth - prev_depth) + prev_update_time;
for (i = 0; i < 2; i++)
{
// int total_flow = get_total_flow_by_time(i, time);
int total_flow = get_total_flow_by_time(i, pflow[i].update_time);
int flow = total_flow - depth_data->last_total_flow[i];
if (flow < 0)
{
flow = 0;
}
depth_data->depth_flow[i] = flow; /* 采样深度对应的流量 */
depth_data->last_total_flow[i] = total_flow;
}
depth_data->sample_count++;
target_sample_depth += depth_config->sample_depth;
add_recod_item();
}
}
}
/*上钻,深度减少*/
else if (enc_value < last_enc_value)
{
// ESP_LOGI(TAG, "enc_value < last_enc_value\n");
uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff);
if (pile_work_dir != PILE_DIR_UP)
{
// 方向改变
depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_UP);
target_sample_depth = (depth_data->depth / depth_config->sample_depth - 1) * depth_config->sample_depth;
if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2)
{
// 小于半个采样长度的合并到下一个采样点
target_sample_depth -= depth_config->sample_depth;
}
}
if (depth_data->depth <= target_sample_depth)
{
// 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点
// 当使用10线编码器时每个脉冲深度达7.6cm当采样间隔为10cm时抖动值太大
if ((prev_depth - depth_data->depth) != 0)
{
int i;
//uint32_t time = (prev_depth - target_sample_depth) * (enc_update_time - prev_update_time) / (prev_depth - depth_data->depth) + prev_update_time;
for (i = 0; i < 2; i++)
{
// int total_flow = get_total_flow_by_time(i, time);
int total_flow = get_total_flow_by_time(i, pflow[i].update_time);
int flow = total_flow - depth_data->last_total_flow[i];
if (flow < 0)
{
flow = 0;
}
depth_data->depth_flow[i] = flow;
depth_data->last_total_flow[i] = total_flow;
}
depth_data->sample_count++;
add_recod_item();
target_sample_depth -= depth_config->sample_depth;
}
}
}
else
{
depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_NONE);
}
if (depth_data->depth < depth_config->inc_pile_depth) // 小于指定深度时才允许行走清零
{
if (pMoveCtx->pile_inc_req == 1)
{
pMoveCtx->pile_inc_req = 0;
reset_depth();
}
}
else
{
if (pMoveCtx->pile_inc_req == 1)
{
pMoveCtx->pile_inc_req = 0;
}
}
}
else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_PAUSE)
{
}
else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_STOP)
{
work_start_time = 0;
}
last_work_state = pile_work_state;
prev_depth = depth_data->depth;
prev_update_time = enc_update_time;
last_enc_value = enc_value;
}
vTaskDelay(pdMS_TO_TICKS(100));
// 500ms计算一次速度
if (++speed_calc_count >= 5)
{
calculate_depth_speed(enc1_value);
speed_calc_count = 0;
}
}
}
void add_recod_item(void)
{
// 每10cm计算一次
record->count = depth_data->sample_count;
ESP_LOGI(TAG, "add_recod_item:id:%d count:%d", record->pile_id, record->count);
memmove(&record->item[1], &record->item[0], sizeof(record->item[0]) * 9);
record->item[0].flow[0] = depth_data->depth_flow[0];
record->item[0].flow[1] = depth_data->depth_flow[1];
record->item[0].total_flow[0] = depth_data->last_total_flow[0];
record->item[0].total_flow[1] = depth_data->last_total_flow[1];
if (depth_config->move_current_channel == 2) // 1
{
record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR];
record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 1];
}
else if (depth_config->move_current_channel == 1)
{
record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR];
record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2];
}
else
{
record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR + 1];
record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2];
}
record->item[0].tilt_x = (short)gWordVar[TILT_SENSER_ADDR];
record->item[0].tilt_y = (short)gWordVar[TILT_SENSER_ADDR + 1];
record->item[0].speed = depth_data->speed; // 每500ms计算一次
record->item[0].depth = depth_data->depth; // 每10ms计算一次
}
extern void save_pile_id(void);
void reset_depth(void)
{
// uint16_t pile_id;
last_sample_depth = 0;
last_flow[0] = 0;
last_flow[1] = 0;
prev_depth = 0;
prev_update_time = 0;
target_sample_depth = 0;
flow_zero();
if (record->count > 0)
{
record->count = 0;
memset(record->item, 0, sizeof(record->item));
}
memset(depth_data, 0, sizeof(*depth_data));
if (record->max_depth >= depth_config->min_valid_depth) // 上一个桩有一定深度数据
{
save_pile_id();
last_pile_id++;
gWordVar[LAST_PILE_ID_ADDR] = last_pile_id;
}
memset(record, 0, sizeof(*record));
record->pile_id = last_pile_id;
// ec11_pcnt_clear(0);
depth_data->depth_offset = -depth_config->depth_offset;
depth_data->depth = depth_config->depth_offset;
enc1_value = 0;
enc1_update_time = 0;
depth_data->pile_work_state_and_direction = PILE_STATE_STOP | PILE_DIR_NONE; // 默认不工作
}
void DEPTH_init(void)
{
pcnt_rotary_encoder_init();
capture_depth_init();
xTaskCreate(depth_task, "depth_task", 4096, NULL, 10, NULL);
}

View File

@ -1,89 +0,0 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "stdlib.h"
#include "config.h"
#include "utils.h"
#include "ads1220.h"
#include "fram.h"
#include "rotary_encoder.h"
#include "esp_log.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "driver/mcpwm.h"
// #include "driver/mcpwm_prelude.h"
// #include "bt_server.h"
// #include "../ble_gatts_server.h"
#include "esp_system.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
#include <string.h>
#include <stdio.h>
static const char *TAG = "depth";
typedef struct
{
uint32_t capture_signal;
mcpwm_capture_signal_t sel_cap_signal;
} capture;
typedef struct capture_event
{
int ch;
uint32_t val;
} capture_event_t;
// #define DEPTH_PIN_CLK GPIO_NUM_36 // 捕获GPIO端口
// #define GPIO_PCNT_PIN_1 36 // Set GPIO 18 as phaseA/C1
// #define GPIO_PCNT_PIN_2 35 // Set GPIO 19 as phaseB/C2
// #define DEPTH_PIN_PULSE 36 //深度脉冲GPIO端口
// #define DEPTH_PIN_CTRL 35 //深度控制GPIO端口
#define FLOW_SYNC_PIN 7 // 捕获GPIO端口 SPI2_nIRQ
#define DEPTH_PIN_PULSE 39 // 深度脉冲GPIO端口 TIM15_CH1
#define DEPTH_PIN_CTRL 38 // 深度控制GPIO端口 TIM15_CH2
#define DEPTH_PIN_ENC_A 42 // 深度脉冲GPIO端口 TIM3_CH1
#define DEPTH_PIN_ENC_B 41 // 深度控制GPIO端口 TIM3_CH2
#define SEND_DATA_TEST 0
#define PILE_STATE_STOP 0x0100
#define PILE_STATE_PAUSE 0x0200
#define PILE_STATE_WORK 0x0300
#define PILE_DIR_NONE 0x01
#define PILE_DIR_UP 0x02
#define PILE_DIR_DOWN 0x03
rotary_encoder_t *encoder_ = NULL; // 编码器测量深度参数
void pcnt_rotary_encoder_init_(void)
{
// Rotary encoder underlying device is represented by a PCNT unit in this example
uint32_t pcnt_unit = 0;
int pulse_pin;
int ctrl_pin;
pulse_pin = DEPTH_PIN_ENC_A;
ctrl_pin = DEPTH_PIN_ENC_B;
// Create rotary encoder instance
rotary_encoder_config_t config = ROTARY_ENCODER_DEFAULT_CONFIG((rotary_encoder_dev_t)pcnt_unit, pulse_pin, ctrl_pin);
config.flags = 0;
ESP_ERROR_CHECK(rotary_encoder_new_ec11(&config, &encoder_));
// Filter out glitch (1us)
ESP_ERROR_CHECK(encoder_->set_glitch_filter(encoder_, 10));
// Start encoder
ESP_ERROR_CHECK(encoder_->start(encoder_));
}

View File

@ -1,233 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "driver/spi_master.h"
#include "driver/mcpwm.h"
#include "esp_log.h"
#include "ads1220.h"
#include "led.h"
#define TAG "ADS1220"
static spi_device_handle_t spi2;
QueueHandle_t drdy_queue = NULL;
int ads1220_ch_now = 0;
uint32_t ads1220_update_time[4];
const uint8_t ch_cmd[4] = {0x0C, 0xA1, 0x0C, 0xB1};
static void SPI2_Init(void)
{
esp_err_t ret;
spi_bus_config_t buscfg2 = {
.miso_io_num = SPI2_PIN_NUM_MISO,
.mosi_io_num = SPI2_PIN_NUM_MOSI,
.sclk_io_num = SPI2_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 8};
spi_device_interface_config_t devcfg2 = {
.clock_speed_hz = 1 * 1000 * 1000, // Clock out at 1 MHz
.mode = 0, // SPI mode 0
.cs_ena_posttrans = 2, // Keep the CS low 2 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than SPI CLK
.spics_io_num = SPI2_PIN_NUM_CS, // CS pin
.queue_size = 1, // We want to be able to queue 7 transactions at a time
// .address_bits = 8,
// .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line
// .command_bits = 8,
};
// Initialize the SPI bus
ret = spi_bus_initialize(ADS1220_HOST, &buscfg2, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
// Attach the ADS1220 to the SPI bus
ret = spi_bus_add_device(ADS1220_HOST, &devcfg2, &spi2);
ESP_ERROR_CHECK(ret);
}
static void IRAM_ATTR ads1220_done_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig,
const cap_event_data_t *edata, void *arg)
{
ads1220_update_time[ads1220_ch_now] = edata->cap_value;
xQueueSendFromISR(drdy_queue, &ads1220_update_time[ads1220_ch_now], NULL);
}
static void drdy_capture_init(void)
{
drdy_queue = xQueueCreate(1, sizeof(uint32_t));
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, ADS1220_DRDY_IO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pullup_en(ADS1220_DRDY_IO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = ads1220_done_handler, // 绑定深度中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf));
}
uint8_t ADS1220_ReadReg(uint8_t reg)
{
uint8_t Val;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RREG | ((reg & 0x03) << 2);
t.length = 2 * 8;
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = t.rx_data[1];
return Val;
}
int32_t ADS1220_ReadData(void)
{
int32_t Val = 0;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RDATA;
t.length = 4 * 8; // Command is 24 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = (t.rx_data[1] << 16) | (t.rx_data[2] << 8) | t.rx_data[3];
if (Val & 0x800000)
{
Val |= 0xFF000000;
}
return Val;
}
void ADS1220_WriteReg(uint8_t reg, uint8_t dat)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
// t.flags = SPI_TRANS_USE_TXDATA;
t.tx_data[0] = ADS1220_CMD_WREG | ((reg & 0x03) << 2);
t.tx_data[1] = dat;
t.length = 2 * 8; // Command is 16 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
}
void ADS1220_WriteCommand(uint8_t cmd)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.length = 8 * 2; // Command is 8 bits
t.tx_data[0] = cmd; // The data is the cmd itself
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
// // ADS1220_CS=0;
// ADS1220_nCS_LOW();
// ADS1220_ReadWriteByte(cmd);
// // ADS1220_CS=1;
// ADS1220_nCS_HIGH();
}
void ADS1220_PowerDown(void)
{
ADS1220_WriteCommand(ADS1220_CMD_POWERDOWN);
}
void ADS1220_StartConv(uint8_t channal)
{
/*
u8 val ;
val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220.CurrentCH = ADS1220_Channal1;
val = val & 0x0f | Channal1;
ADS1220_WriteReg(ADS1220_REG0, val );
*/
ADS1220_WriteCommand(ADS1220_CMD_START);
}
void ADS1220_Reset(void)
{
ADS1220_WriteCommand(ADS1220_CMD_RESET);
}
void ADS1220_PGASet(uint8_t gain)
{
uint8_t val;
val = ADS1220_ReadReg(ADS1220_REG0);
val = (val & 0xF1) | gain;
ADS1220_WriteReg(ADS1220_REG0, val);
// val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220_StartConv(ADS1220_Channal1);
}
void ADS1220_Config(void)
{
static uint8_t read[4];
ADS1220_WriteCommand(ADS1220_CMD_RESET);
vTaskDelay(10);
ADS1220_WriteReg(ADS1220_REG0, 0xa0);
ADS1220_WriteReg(ADS1220_REG1, 0x20);
ADS1220_WriteReg(ADS1220_REG2, 0x20);
ADS1220_WriteReg(ADS1220_REG3, 0x00);
read[0] = ADS1220_ReadReg(ADS1220_REG0);
read[1] = ADS1220_ReadReg(ADS1220_REG1);
read[2] = ADS1220_ReadReg(ADS1220_REG2);
read[3] = ADS1220_ReadReg(ADS1220_REG3);
ESP_LOGI(TAG, "ads1220 reg %02x %02x %02x %02x \n", read[0], read[1], read[2], read[3]);
}
void ads1220_init(void)
{
SPI2_Init();
drdy_capture_init();
ADS1220_Config();
ads1220_ch_now = 0;
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ads1220_ch_now]);
ADS1220_WriteCommand(ADS1220_CMD_START);
}
int ads1220_read_flow(int32_t *ad_raw_p, int *ad_ch_p, uint32_t *ad_update_time_p)
{
uint32_t io_num;
if (pdFALSE == xQueueReceive(drdy_queue, &io_num, pdMS_TO_TICKS(100)))
{
ESP_LOGI(TAG, "ads1220 wait drdy_queue timeout!");
ads1220_init(); // 但是请注意init会让两通道都初始化了
*ad_ch_p = ads1220_ch_now;
return -1;
}
int ad_ch = ads1220_ch_now;
int32_t ad_raw = ADS1220_ReadData();
ads1220_ch_now++;
if (ads1220_ch_now >= sizeof(ch_cmd))
{
ads1220_ch_now = 0;
}
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ads1220_ch_now]);
ADS1220_WriteCommand(ADS1220_CMD_START);
*ad_raw_p = ad_raw;
*ad_ch_p = ad_ch;
*ad_update_time_p = ads1220_update_time[ad_ch];
return 0;
}

View File

@ -1,216 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_err.h"
#include "esp_log.h"
// #include "soc/rtc.h"
#include "flow.h"
#include "ads1220.h"
#include "input_type2.h"
#include "led.h"
#include "gwordvar.h"
#include "utils.h"
const static char *TAG = "flow";
cal_4_20ma_t *cal_4_20ma = (cal_4_20ma_t *)&gWordVar[CAL_4_20MA_ADDR];
flow_config_t *flow_config = (flow_config_t *)&gWordVar[FLOW_CONFIG_ADDR];
flow_t *pflow = (flow_t *)&gWordVar[FLOW_REG_ADDR];
extern uint32_t rtc_clk_apb_freq;
static uint32_t volatile last_ccr[2];
static int flow_rem[2];
static uint8_t timeout[2];
// 获取给定时刻累计流量
int get_total_flow_by_time(int ch, uint32_t time)
{
int delta_t;
int delta_flow;
if (ch > 1)
{
return 0;
}
delta_t = abs_sub_uint32(time, pflow[ch].update_time) / (APB_CLK_FREQ / 1000000); // 换算成us
delta_flow = pflow[ch].flow * delta_t / 60 / 100;
return pflow[ch].total_flow + delta_flow;
}
void zero_totalflow(int ch)
{
if (ch > 1)
{
return;
}
pflow[ch].total_flow = 0;
flow_rem[ch] = 0;
}
void flow_zero(void)
{
memset(pflow, 0, sizeof(flow_t) * 2);
for (int i = 0; i < 2; i++)
{
last_ccr[i] = 0;
flow_rem[i] = 0;
timeout[i] = 0;
t15_ccr[i] = 0;
t15_ccr_times[i] = 0;
}
}
void flow_input_type1_calculate(void)
{
int ret = 0;
int32_t ad_raw_data = 0;
int ad_ch = 0, flow_ch = 0;
int time_diff = 0;
uint32_t ad_update_time = 0;
if (ads1220_read_flow(&ad_raw_data, &ad_ch, &ad_update_time) == 0)
{
ad_raw_data = ad_raw_data / 128;
gWordVar[AD_RAW_REG_ADDR + ad_ch] = ad_raw_data / 2;
if (ad_ch != 1 && ad_ch != 3) // 1, 3命令所测的电流是我们想要的
{
return;
}
LED_Toggle(LED2_GPIO_PIN);
flow_ch = ad_ch / 2;
if (pflow[flow_ch].update_time == 0) // 第一次测得数据,不计算
{
goto exit;
}
// 瞬时流量换算
ad_flow_cal_t *cal = flow_config->ad_cal;
pflow[flow_ch].flow_ = scale(ad_raw_data, cal_4_20ma->ch[flow_ch].ad_4ma, cal_4_20ma->ch[flow_ch].ad_20ma, cal[flow_ch].flow_min, cal[flow_ch].flow_max);
if (pflow[flow_ch].flow_ < flow_config->min_flow[flow_ch]) // 小流量切除
{
pflow[flow_ch].flow = 0;
}
else
{
pflow[flow_ch].flow = pflow[flow_ch].flow_;
}
// 累计流量计算
int t_flow; // time_diff时间段总流量
time_diff = abs_sub_uint32(ad_update_time, pflow[flow_ch].update_time);
// 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为1us
// flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s
// t_diff = time_diff / 1000 将时间差换算成秒
// t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL
// 取出0.01L的整数部分累加,余数部分和下次值累加
// t_flow = pflow[i].flow * 1000 * time_diff / 1000000 / 60;
int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000);
// if (ad_ch == 3) ESP_LOGI(TAG, "time_diff_us:%d", time_diff_us);
t_flow = pflow[flow_ch].flow * (long long)time_diff_us / 60 / 100; //(5 * 60);
flow_rem[flow_ch] += t_flow;
int sub_flow = flow_rem[flow_ch] / 10000;
pflow[flow_ch].total_flow += sub_flow;
flow_rem[flow_ch] = flow_rem[flow_ch] - sub_flow * 10000;
exit:
pflow[flow_ch].update_time = ad_update_time;
// ESP_LOGI(TAG, "flow_ch %d: %5d %5ld, %5d %5ld", flow_ch, pflow[0].flow, pflow[0].total_flow, pflow[1].flow, pflow[1].total_flow);
return;
}
}
void flow_input_type2_calculate(void)
{
vTaskDelay(pdMS_TO_TICKS(100));
int ch;
for (ch = 0; ch < 2; ch++)
{
if (t15_ccr_times[ch] > 0)
{
int ccr_times;
int time_diff;
uint32_t ccr;
// __disable_irq();
ccr_times = t15_ccr_times[ch];
t15_ccr_times[ch] = 0;
ccr = t15_ccr[ch];
ccr = ccr / (rtc_clk_apb_freq / 1000000);
// __enable_irq();
time_diff = ccr - last_ccr[ch];
// ESP_LOGI(TAG, "(type2) t15_ccr_times[%d]: %lu %d time_diff: %d", ch, ccr, ccr_times, time_diff);
// ESP_LOGI(TAG,"rtc_clk_apb_freq : %lu\n", rtc_clk_apb_freq);
if (time_diff != 0)
{
int t_flow;
pflow[ch].flow_ = flow_config->pulse_coef[ch] * 600 * (int64_t)ccr_times / time_diff;
if (pflow[ch].flow_ < flow_config->min_flow[ch])
{
pflow[ch].flow = 0;
}
else
{
pflow[ch].flow = pflow[ch].flow_;
}
t_flow = pflow[ch].flow * time_diff / (5 * 60);
flow_rem[ch] += t_flow;
pflow[ch].total_flow += flow_rem[ch] / 10000;
flow_rem[ch] = flow_rem[ch] % 10000;
pflow[ch].update_time = ccr;
last_ccr[ch] = ccr;
timeout[ch] = 0;
// ESP_LOGI(TAG, "(type2) pflow[%d].flow: %u", ch ,pflow[ch].flow);
}
}
else if (++timeout[ch] > 5)
{
timeout[ch] = 0;
pflow[ch].flow = 0;
pflow[ch].flow_ = 0;
}
}
}
void flow_task(void *arg)
{
flow_config->input_type = 1;
while (1)
{
switch (flow_config->input_type)
{
case 1:
{
flow_input_type1_calculate();
break;
}
case 2:
{
flow_input_type2_calculate();
break;
}
default:
ESP_LOGI(TAG, "Flow input type not illegality! Can not measure flow.");
vTaskDelay(pdMS_TO_TICKS(100));
break;
}
}
}
void flow_init(void)
{
ads1220_init();
flow_input_type2_init();
led_init();
xTaskCreate(flow_task, "flow_task", 4096, NULL, 10, NULL);
}

View File

@ -1,70 +0,0 @@
#ifndef __ADS1220_H
#define __ADS1220_H
#include <stdint.h>
#include "freertos/queue.h"
#define ADS1220_DRDY_IO 7
#define SPI2_PIN_NUM_MISO 6
#define SPI2_PIN_NUM_MOSI 5
#define SPI2_PIN_NUM_CLK 16
#define SPI2_PIN_NUM_CS 15
#define ADS1220_HOST SPI2_HOST
#define PARALLEL_LINES 16
#define ADS1220_nCS_HIGH() gpio_set_level(GPIO_NUM_38, 1)
#define ADS1220_nCS_LOW() gpio_set_level(GPIO_NUM_38, 0)
#define ADS1220_CMD_WREG 0x40
#define ADS1220_CMD_RREG 0x20
#define ADS1220_CMD_RESET 0x06
#define ADS1220_CMD_START 0x08
#define ADS1220_CMD_POWERDOWN 0x02
#define ADS1220_CMD_RDATA 0x10
#define Channal1 0x00
#define Channal2 0x10
#define Channal3 0x20
#define Channal4 0x30
#define ADS1220_REG0 0x00
#define ADS1220_REG1 0x01
#define ADS1220_REG2 0x02
#define ADS1220_REG3 0x03
#define PGAGain1 0x00
#define PGAGain2 0x02
#define PGAGain4 0x04
#define PGAGain8 0x06
#define PGAGain16 0x08
#define PGAGain32 0x0A
#define PGAGain64 0x0C
#define PGAGain128 0x0E
#define ADS1220_Standby 0
#define ADS1220_ConvStart 1
#define ADS1220_ConvFinish 2
#define ADS1220_Channal1 0
#define ADS1220_Channal2 1
#define ADS1220_Channal3 2
#define ADS1220_Channal4 3
int ADS1220_get_rate(void);
void ADS1220_set_rate(int i);
void ADS1220_Config(void);
void ADS1220_StartConv(uint8_t channal);
void ADS1220_Reset(void);
void ADS1220_PowerDown(void);
void ADS1220_PGASet(uint8_t gain);
void ADS1220_WriteCommand(uint8_t cmd);
int32_t ADS1220_ReadData(void);
void ADS1220_WriteReg(uint8_t reg,uint8_t dat);
uint8_t ADS1220_ReadReg(uint8_t reg);
uint8_t ADS1220_ReadWriteByte(uint8_t dat);
void ads1220_init(void);
int ads1220_read_flow(int32_t *ad_raw_p, int *ad_ch_p, uint32_t *ad_update_time_p);
#endif

View File

@ -1,51 +0,0 @@
#ifndef __FLOW_H
#define __FLOW_H
#include <stdint.h>
typedef struct
{
uint16_t magic;
struct _ch
{
uint16_t ad_4ma;
uint16_t ad_20ma;
} ch[2];
} cal_4_20ma_t;
typedef struct
{
int16_t flow_min;
int16_t flow_max;
} ad_flow_cal_t; //存储ad转换的最大流量和最小流量
typedef struct
{
uint16_t magic;
uint16_t input_type; // 1: 4~20ma 2: 0~3.6K
int16_t min_flow[2]; // 小流量切除
ad_flow_cal_t ad_cal[2];
uint16_t pulse_coef[2];
uint16_t rsv[6];
} flow_config_t;
typedef struct
{
int16_t flow_;
int16_t flow;
int32_t total_flow;
uint32_t update_time;
} flow_t;
extern cal_4_20ma_t *cal_4_20ma;
extern flow_config_t *flow_config;
extern flow_t *pflow;
void flow_init(void);
void zero_totalflow(int ch);
void flow_zero(void);
int get_total_flow_by_time(int ch, uint32_t time);
#endif

View File

@ -1,14 +0,0 @@
#ifndef __INPUT_TYPE2_H
#define __INPUT_TYPE2_H
#include <stdint.h>
#define FLOW1_PIN_ECHO GPIO_NUM_39
#define FLOW2_PIN_ECHO GPIO_NUM_38
extern uint32_t volatile t15_ccr[2];
extern uint16_t volatile t15_ccr_times[2];
void flow_input_type2_init(void);
#endif

View File

@ -1,78 +0,0 @@
#include "freertos/FreeRTOS.h"
#include "driver/mcpwm.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_log.h"
#include "input_type2.h"
const static char *TAG = "flow_input_type2";
uint32_t volatile t15_ccr[2];
uint16_t volatile t15_ccr_times[2];
static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
t15_ccr[0] = edata->cap_value;
t15_ccr_times[0]++;
return high_task_wakeup == pdFALSE;
}
void capture_flow1_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pulldown_en(FLOW1_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf));
ESP_LOGI(TAG, "capture_flow_init");
}
static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
t15_ccr[1] = edata->cap_value;
// t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
t15_ccr_times[1]++;
// send measurement back though queue
// xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup);
return high_task_wakeup == pdFALSE;
}
void capture_flow2_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf));
ESP_LOGI(TAG, "capture_flow_init");
}
void flow_input_type2_init(void)
{
capture_flow1_init();
capture_flow2_init();
}

View File

@ -1,33 +0,0 @@
#ifndef __BL0939_H
#define __BL0939_H
#include <stdint.h>
#define BL0939_HOST SPI3_HOST
#define SPI1_PIN_NUM_MISO 37
#define SPI1_PIN_NUM_MOSI 36
#define SPI1_PIN_NUM_CLK 35
#define SPI1_PIN_NUM_CS 40
typedef struct
{
uint16_t status; // 0:未开始 1:开始 2:结束
uint16_t time_count; //持续时间
uint16_t pile_inc_req;
} move_t;
extern move_t *pMoveCtx;
void bl0939_reset(void);
int bl0939_get_current_A(void);
int bl0939_get_current_B(void);
int bl0939_get_voltage(void);
//DMA
void bl0939_get_abv(uint8_t * buf);
int bl0939_parse_abv(uint8_t * buf,unsigned int * data);
void BL0939_init(void);
#endif

View File

@ -1,95 +0,0 @@
#ifndef __DEPTH_H
#define __DEPTH_H
#include <stdint.h>
#define FLOW_SYNC_PIN 7 // 捕获GPIO端口 SPI2_nIRQ
#define DEPTH_PIN_PULSE 39 // 深度脉冲GPIO端口 TIM15_CH1
#define DEPTH_PIN_CTRL 38 // 深度控制GPIO端口 TIM15_CH2
#define DEPTH_PIN_ENC_A 42 // 深度脉冲GPIO端口 TIM3_CH1
#define DEPTH_PIN_ENC_B 41 // 深度控制GPIO端口 TIM3_CH2
#define SEND_DATA_TEST 0
#define PILE_STATE_STOP 0x0100
#define PILE_STATE_PAUSE 0x0200
#define PILE_STATE_WORK 0x0300
#define PILE_DIR_NONE 0x01
#define PILE_DIR_UP 0x02
#define PILE_DIR_DOWN 0x03
typedef struct
{
uint16_t magic;
uint8_t input_type; // 0正交 1:正交反向 2:方向脉冲 3:方向脉冲反向
uint8_t port; // 编码器端口
uint16_t N; //编码器系数分子
uint16_t M; //编码器系数分母
// int pluse_coef; // 脉冲系数0.001mm
int16_t min_depth; // 最小深度 mm
int16_t max_depth; // 最大深度 mm
int16_t sample_depth; // 采样深度 mm
int16_t depth_offset; // 默认深度偏移
int16_t min_valid_depth; // 最小有效深度
int16_t inc_pile_depth; // 允许换桩深度
uint16_t current_on_threshold; // 行走电机开启电流
uint16_t current_off_threshold; // 行走电机关闭电流
uint16_t move_on_duratino; // 持续时间
uint16_t move_off_duration; // 持续时间
uint16_t move_current_channel; //行走电流通道
} depth_config_t;
typedef struct
{
uint16_t pile_work_state_and_direction; // 12
int16_t speed; // 13
int16_t depth; // 14
uint16_t sample_count; // 15
uint16_t depth_flow[2]; // 16~17
uint32_t last_total_flow[2]; //
int16_t depth_offset; // 22
uint16_t one_pile_work_time; //23 系统工作时间
// uint32_t update_time;
// int16_t tilt_x;
// int16_t tilt_y;
// uint16_t current1;
// uint16_t current2;
// uint16_t current3;
} depth_t;
typedef struct
{
int16_t max_depth;
uint16_t pile_id;
uint16_t count;
// uint16_t work_time;
struct _item
{
int16_t speed;
int16_t depth;
int16_t flow[2];
uint32_t total_flow[2];
int16_t tilt_x;
int16_t tilt_y;
uint16_t current1;
uint16_t current2;
} item[10];
} record_t;
extern depth_config_t *depth_config;
extern depth_t *depth_data;
extern record_t *record;
void DEPTH_init(void);
void reset_depth(void);
void add_recod_item(void);
#endif

680
main/stm32/ModbusM.c Normal file
View File

@ -0,0 +1,680 @@
#include <string.h>
#include <stdint.h>
#include "ModbusM.h"
#include "ModbusS.h"
#include "config.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "uart.h"
#include "driver/uart.h"
#define ZB_CHANNEL 1
extern uint16_t gWordVar[];
//uint16_t g_tmp[100];
device_t zb_device[ZB_CHANNEL];
send_t zb_send[16];
#define GetTicks xTaskGetTickCount
#define UART1_TXBUF_SIZE 256
int zbapi_send_write(device_t *device, send_t *sender);
int zbapi_send_req(device_t *device);
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
//static float pow_user(float x, float y)
//{
// int i;
// float tmp = 1;
// for (i = 0; i < y; i++)
// {
// tmp = tmp * x;
// }
// return tmp;
//}
uint16_t bin2bcd(uint16_t bin)
{
uint16_t bcd;
uint8_t buf[4];
if (bin > 9999)
{
bin = 9999;
}
buf[0] = bin % 10;
bin /= 10;
buf[1] = bin % 10;
bin /= 10;
buf[2] = bin % 10;
buf[3] = bin / 10;
bcd = buf[0] | (buf[1] << 4) | (buf[2] << 8) | (buf[3] << 12);
return bcd;
}
int min(int x, int y)
{
if (x < y)
return x;
else
return y;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>sn ֵ
uint8_t get_new_sn(int device_id)
{
int i;
int sn = 0;
for (i = 0; i < 16; i++)
{
if (zb_send[i].device_id == device_id)
{
sn = max(zb_send[i].sn, sn);
}
}
return sn + 1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8>Сsn<73><6E>Ӧ<EFBFBD><D3A6><EFBFBD>±<EFBFBD>
int device_get_send(int device_id)
{
int i;
int sn = 255;
int min_index = -1;
for (i = 0; i < 16; i++)
{
if (zb_send[i].device_id == device_id)
{
if (zb_send[i].sn < sn)
{
sn = zb_send[i].sn;
min_index = i;
}
}
}
return min_index;
}
void on_in_pack_error(device_t *device)
{
if (device->in_err_cnt[device->in_index] < device->in->max_err_cnt)
{
if (++device->in_err_cnt[device->in_index] >= device->in->max_err_cnt)
{
const packet_t *in_pack = device->in->packets + device->in_index;
int i;
for (i = 0; i < in_pack->length; i++)
{
uint32_t reg_addr = in_pack->local_addr + i;
if (reg_addr < gWORD_SIZE)
{
gWordVar[reg_addr] = 0;
}
}
if (device->protocol == 255)
{
if (in_pack->slave > 0 && in_pack->slave <= 10)
{
int i;
for (i = 0; i < 10; i++)
{
gWordVar[in_pack->local_addr] = 0;
}
}
if (in_pack->slave == 0)
{
gWordVar[64 + 10] = 0;
}
}
// on_data_error(device);
}
}
}
extern int page;
void modbus_master_poll(int n)
{
uint32_t now = GetTicks();
// printf("status == %d\n",zb_device[n].status);
if (zb_device[n].status == 0) // 空闲状态
{
if (zb_device[n].out_pending > 0) ////如果有发送请求先处理发送
{
// printf("out_pending > 0\n");
int send_index = device_get_send(n);
if (send_index >= 0)
{
if (now >= zb_send[send_index].next_try_time)
{
zb_device[n].out_index = send_index;
zb_device[n].send_req_time = now;
zbapi_send_write(&zb_device[n], &zb_send[send_index]);
zb_device[n].status = 0x10;
return;
}
}
else
{
zb_device[n].out_pending = 0;
}
}
if (now >= zb_device[n].next_scan_time)
{
// printf("now >= zb_device[%d]\n",n);
zb_device[n].send_req_time = now;
zbapi_send_req(&zb_device[n]);
zb_device[n].status = 2;
}
}
else if (zb_device[n].status == 1 || zb_device[n].status == 2) //
{
if ((now - zb_device[n].send_req_time) > zb_device[n].in->time_out * 100)
{
zb_device[n].status = 0; //<2F><>ʱ
zb_device[n].ErrCode = 0x01;
zb_device[n].ErrCount++;
on_in_pack_error(&zb_device[n]);
if ((++zb_device[n].try_times >= zb_device[n].in->max_try_times) ||
(zb_device[n].in_err_cnt[zb_device[n].in_index] >= zb_device[n].in->max_err_cnt))
{
if (++zb_device[n].in_index >= zb_device[n].in->packet_cnt)
{
zb_device[n].in_index = 0;
zb_device[n].group_start_time = now;
}
//zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate*10;
zb_device[n].try_times = 0;
}
zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate * 10;
zb_device[n].status = 0;
}
}
else if (zb_device[n].status == 3) // <20><><EFBFBD>յ<EFBFBD><D5B5>ظ<EFBFBD>
{
if (++zb_device[n].in_index >= zb_device[n].in->packet_cnt)
{
zb_device[n].in_index = 0;
zb_device[n].group_start_time = now; //+ zb_device[n].in->scan_rate*10;
}
zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate * 10;
zb_device[n].status = 255;
zb_device[n].try_times = 0;
}
else if (zb_device[n].status == 0x10) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>߳<EFBFBD>ʱ
{
int index = zb_device[n].out_index;
if ((now - zb_device[n].send_req_time) > zb_device[n].in->time_out * 100)
{
zb_device[n].status = 0; //<2F><>ʱ
zb_device[n].ErrCode = 0x01;
zb_device[n].ErrCount++;
if (++zb_send[index].try_times >= zb_device[n].out->max_try_times) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
{
zb_send[index].device_id = 0xff;
}
else
{
zb_send[index].next_try_time = now + zb_device[n].out->try_space * 100;
}
zb_device[n].status = 0;
zb_device[n].try_times = 0;
}
}
else if (zb_device[n].status == 0x11) // <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>
{
zb_send[zb_device[n].out_index].device_id = 0xff;
zb_device[n].status = 255;
zb_device[n].try_times = 0;
}
else
{
if ((now - zb_device[n].revice_resp_time) >= (zb_device[n].in->scan_space))
{
zb_device[n].status = 0;
zb_device[n].try_times = 0;
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>
int intersection(int x0, int x1, int y0, int y1, int *s, int *e)
{
int ret = 0;
if ((y0 >= x0) && (y0 < x1))
{
*s = y0;
*e = min(x1, y1);
ret = 1;
}
else if ((y1 > x0) && (y1 <= x1))
{
*s = y1 - 1;
*e = min(x1, y1);
ret = 1;
}
else if ((x0 >= y0) && (x0 < y1))
{
*s = x0;
*e = min(y1, x1);
ret = 1;
}
else if ((x1 > y0) && (x1 <= y1))
{
*s = x1 - 1;
*e = min(y1, x1);
ret = 1;
}
return ret;
}
int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length)
{
int i, j;
int ret = 0;
for (i = 0; i < ZB_CHANNEL; i++)
{
if (zb_device[i].out == NULL)
{
continue;
}
for (j = 0; j < zb_device[i].out->packet_cnt; j++)
{
int s1, e1;
int s2, e2;
int s, e;
int n;
s1 = zb_device[i].out->packets[j].local_addr;
e1 = zb_device[i].out->packets[j].local_addr + zb_device[i].out->packets[j].length;
s2 = addr;
e2 = addr + length;
if (intersection(s1, e1, s2, e2, &s, &e))
//if((s2 >= s1 && s2 < e1) || (e2 >= s1 && s2 < e1))
{
for (n = 0; n < 16; n++)
{
if (zb_send[n].device_id == 0xff)
{
zb_send[n].sn = get_new_sn(i);
zb_send[n].device_id = i;
zb_send[n].packet_index = j;
zb_send[n].address = s;
zb_send[n].length = e - s;
zb_send[n].next_try_time = 0;
zb_send[n].try_times = 0;
zb_device[i].out_pending++;
ret = 1;
break;
}
}
}
}
}
return ret;
}
//extern uint8_t Uart3TxBuf[];
//#define txbuf Uart3TxBuf
int zbapi_send_req(device_t *device)
{
if (device->protocol == 255)
{
device->txbuf[0] = device->in->packets[device->in_index].slave;
device->txbuf[1] = 0x5a;
device->txbuf[2] = 0xaa;
device->write(device->txbuf, 3);
}
else
{
uint16_t crc;
device->txbuf[0] = device->in->packets[device->in_index].slave;
device->txbuf[1] = device->in->packets[device->in_index].funcode;
device->txbuf[2] = device->in->packets[device->in_index].address >> 8;
device->txbuf[3] = device->in->packets[device->in_index].address & 0xff;
device->txbuf[4] = device->in->packets[device->in_index].length >> 8;
device->txbuf[5] = device->in->packets[device->in_index].length & 0xff;
crc = crc16(device->txbuf, 6);
device->txbuf[6] = crc >> 8;
device->txbuf[7] = crc & 0xff;
device->write(device->txbuf, 8);
}
return 0;
}
int zbapi_send_write(device_t *device, send_t *sender)
{
{
int n = 0;
uint16_t crc;
const packet_t *out_pack = &device->out->packets[sender->packet_index];
if (sender->length == 0)
{
return 0;
}
device->txbuf[0] = device->out->packets[sender->packet_index].slave;
if (sender->length > 1)
{
int addr = out_pack->address + (sender->address - out_pack->local_addr);
int i;
int len;
device->txbuf[1] = 0x10;
device->txbuf[2] = addr >> 8;
device->txbuf[3] = addr & 0xff;
device->txbuf[4] = sender->length >> 8;
device->txbuf[5] = sender->length & 0xff;
device->txbuf[6] = (sender->length * 2) & 0xff;
len = 7;
for (i = 0; i < sender->length; i++)
{
uint16_t reg16 = gWordVar[sender->address + i];
if (out_pack->device_type == 5)
{
reg16 = bin2bcd(reg16);
}
device->txbuf[len++] = reg16 >> 8;
device->txbuf[len++] = reg16 & 0xff;
}
crc = crc16(device->txbuf, len);
device->txbuf[len++] = crc >> 8;
device->txbuf[len++] = crc & 0xff;
n += len;
}
else
{
int addr = out_pack->address + (sender->address - out_pack->local_addr);
uint16_t reg16 = gWordVar[sender->address];
device->txbuf[1] = 0x06;
device->txbuf[2] = addr >> 8;
device->txbuf[3] = addr & 0xff;
if (out_pack->device_type == 5)
{
reg16 = bin2bcd(reg16);
}
if ((device->protocol == 5) || (device->protocol == 6))
{
reg16 *= 10;
}
device->txbuf[4] = reg16 >> 8;
device->txbuf[5] = reg16 & 0xff;
crc = crc16(device->txbuf, 6);
device->txbuf[6] = crc >> 8;
device->txbuf[7] = crc & 0xff;
n += 8;
}
if (device->write != NULL)
{
device->write(device->txbuf, n);
}
}
return 1;
}
extern uint16_t Is_SetFromScreen;
int modbus_master_on_revice(int ch, uint8_t *rxbuf, int length)
{
int i;
// uint8_t src_addr[8];
if (length < 4)
{
return -1;
}
i = ch;
//for(i=0; i<ZB_CHANNEL; i++)//1
{
if (zb_device[i].status == 2)
{
zb_device[i].revice_resp_time = GetTicks();
{
int index = zb_device[i].in_index;
if ((zb_device[i].in->packets[index].slave == rxbuf[0]) &&
zb_device[i].in->packets[index].funcode == rxbuf[1])
{
uint16_t crcChk = crc16(rxbuf, length - 2);
uint16_t crcData = (rxbuf[length - 2] << 8) | rxbuf[length - 1];
if (crcData != crcChk)
{
zb_device[i].ErrCode = 2; //CRC error
zb_device[i].ErrCount++;
}
else if (rxbuf[0] != zb_device[i].in->packets[index].slave)
{
zb_device[i].ErrCode = 3; //ADD error
zb_device[i].ErrCount++;
}
else if (rxbuf[1] != zb_device[i].in->packets[index].funcode)
{
zb_device[i].ErrCode = 4; //Fun err;
zb_device[i].ErrCount++;
}
else if (rxbuf[2] != (zb_device[i].in->packets[index].length * 2))
{
zb_device[i].ErrCode = 1; //byte miss
zb_device[i].ErrCount++;
}
else
{
int n = 0;
// uint32_t reg32;
uint16_t addr = zb_device[i].in->packets[index].local_addr;
uint8_t len = rxbuf[2] / 2;
if (addr >= gWORD_SIZE)
{
zb_device[i].ErrCode = 5; //regaddr err;
goto done;
}
zb_device[i].ErrCode = 0;
switch (zb_device[i].in->packets[index].device_type)
{
default:
for (n = 0; n < len; n++)
{
if (addr + n < gWORD_SIZE)
{
gWordVar[addr + n] = (rxbuf[3 + n * 2] << 8) | (rxbuf[3 + n * 2 + 1]);
}
else
{
break;
}
}
break;
}
zb_device[i].in_err_cnt[zb_device[i].in_index] = 0;
}
done:
zb_device[i].status = 3;
}
}
}
else if (zb_device[i].status == 0x10)
{
zb_device[i].revice_resp_time = GetTicks();
//if(memcmp(src_addr,((zb_dev_t*)zb_device[i].ext)->zb_addr,8) == 0)
{
zb_device[i].status = 0x11;
}
}
}
return 0;
}
//int meter_count = 4;
//#define meter_count meter_cfg.count
//const int reg_offset[] = {0, 2, 3, 4, 1};
//static char input_buf[1][414];
//static char output_buf[1][212];
static char in_err_cnt_buf[1][25];
struct input{
input_t input;
packet_t packet[5];
};
struct output{
output_t output;
packet_t packet[5];
};
struct input input1;
struct output output1;
extern int uart1_tx_start(uint8_t *data, int length);
extern uint8_t uart1_txbuf[];
//static uint8_t uart_txbuf[ 256 ];
//static uint8_t uart_rxbuf[ 256 ];
static int uart_send(uint8_t *buf, int len)
{
// uart1_tx_start(buf, len);
uart_write_bytes(RS485_UART_PORT_NUM, buf, len);
//HAL_UART_Transmit_DMA(&huart1,buf,len);
return len;
}
int ModbusM_init(void)
{
int i = 0;
// int meter_count[4] = {0, 0, 0, 0};
// int size;
// char *p;
// int n;
// uint8_t *in_err_cnt;
zb_device[0].txbuf = uart1_txbuf;
zb_device[0].txbuf_size = UART1_TXBUF_SIZE;
zb_device[0].write = uart_send;
{
input_t *input;
output_t *output;
uint8_t *in_err_cnt;
// memset(input_buf[i], 0, sizeof(input_buf[i]));
// memset(output_buf[i], 0, sizeof(output_buf[i]));
// memset(in_err_cnt_buf[i], 0, sizeof(in_err_cnt_buf[i]));
output = &output1.output;
input = &input1.input;
in_err_cnt = (uint8_t *)in_err_cnt_buf[i];
zb_device[i].in_err_cnt = in_err_cnt;
input->scan_rate = 10; //*10ms
input->time_out = 10; //*100ms
input->max_try_times = 2;
input->scan_space = 50; //*10ms
input->max_err_cnt = 30;
output->max_try_times = 3;
output->try_space = 40;
zb_device[i].channl = i;
zb_device[i].next_scan_time = 0;
zb_device[i].status = 0;
zb_device[i].try_times = 0;
zb_device[i].in_index = 0;
zb_device[i].out_pending = 0;
zb_device[i].in_err_cnt = in_err_cnt;
zb_device[i].in = input;
zb_device[i].out = output;
// zb_device[i].ext = &serial_port_cfg[i];
}
{
device_t *dev = (device_t *)&zb_device;
dev->in->packets[dev->in->packet_cnt].slave = 1;
dev->in->packets[dev->in->packet_cnt].funcode = 3;
dev->in->packets[dev->in->packet_cnt].address = 0;
dev->in->packets[dev->in->packet_cnt].length = 3;
dev->in->packets[dev->in->packet_cnt].device_type = 0;
dev->in->packets[dev->in->packet_cnt].local_addr = TILT_SENSER_ADDR;
dev->in->packets[dev->in->packet_cnt].ch = 0;
dev->in->packet_cnt++;
dev->out->packets[dev->out->packet_cnt].slave = 1;
dev->out->packets[dev->out->packet_cnt].funcode = 6;
dev->out->packets[dev->out->packet_cnt].local_addr = 10;
dev->out->packets[dev->out->packet_cnt].length = 1;
dev->out->packets[dev->out->packet_cnt].address = 5;
dev->out->packets[dev->out->packet_cnt].device_type = 0;
dev->in->packets[dev->in->packet_cnt].ch = 0;
dev->out->packet_cnt++;
}
return 0;
}
extern int meter_type;
void ModbusM_reinit(void)
{
int i;
for (i = 64; i < 64 + 128; i++)
{
gWordVar[i] = 0;
}
ModbusM_init();
}
int fill_data(uint8_t *pData, uint16_t local_addr, uint8_t remote_offset, uint8_t length)
{
uint16_t *pWordVar;
int i;
*pData++ = remote_offset;
*pData++ = length;
pWordVar = &gWordVar[local_addr];
for (i = 0; i < length; i++)
{
*pData++ = *pWordVar >> 8;
*pData++ = *pWordVar & 0xff;
pWordVar++;
}
return i * 2 + 2;
}
int build_data(int dest_addr, const int *src_addr_map, int length)
{
int i;
int change_cnt = 0;
for (i = 0; i < length; i++)
{
int src_addr = src_addr_map[i];
if (dest_addr < gWORD_SIZE && src_addr >= 0 && src_addr < gWORD_SIZE)
{
if (gWordVar[dest_addr] != gWordVar[src_addr])
{
gWordVar[dest_addr] = gWordVar[src_addr];
change_cnt++;
}
}
else
{
return -1;
}
dest_addr++;
}
return change_cnt;
}
int copy_data(int dest_addr, int src_addr, int length)
{
int i;
int change_cnt = 0;
for (i = 0; i < length; i++)
{
//int src_addr = src_addr_map[i];
if (dest_addr < gWORD_SIZE && src_addr >= 0 && src_addr < gWORD_SIZE)
{
if (gWordVar[dest_addr] != gWordVar[src_addr])
{
gWordVar[dest_addr] = gWordVar[src_addr];
change_cnt++;
}
}
else
{
return -1;
}
dest_addr++;
src_addr++;
}
return change_cnt;
}

120
main/stm32/ModbusM.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef _MODBUSM_H_
#define _MODBUSM_H_
#define uint8 unsigned char
#define uint16 unsigned short
#define uint32 unsigned int
typedef struct _MODBUS_MASTRT_
{
uint8 Status;
uint8 ErrCode;
uint8 Slave;
uint8 Function;
uint8 PackId;
uint8 Length;
uint16 Address;
uint16 *Data;
uint32 txtime;
uint32 rxtime;
uint16 TxCont;
uint16 TimeOut;
uint16 CrcErr;
uint16 ByteMiss;
uint16 OtherErr;
}MODBUS_MASTERT_T;
typedef struct _MODBUS_READ_T_
{
uint8 SaveAdd;
uint8 Length;
uint16 RegAdd;
uint16 *pDat;
}MODBUS_READ_T;
typedef struct _packet_
{
uint8_t device_type;
uint8_t slave;
uint8_t funcode;
uint8_t ch;
uint16_t length;
uint16_t address;
uint16_t local_addr;
uint16_t ext_flg;
const void* ext;
}packet_t;
typedef struct _input_
{
uint8_t packet_cnt;
uint8_t max_try_times;
uint8_t time_out;
uint16_t scan_rate;
uint16_t scan_space;
uint8_t max_err_cnt;
uint8_t ch;
uint8_t rsv[2];
packet_t packets[1];
}input_t;
typedef struct _output_
{
uint8_t packet_cnt;
uint8_t max_try_times;
uint8_t try_space;
uint8_t rsv;
packet_t packets[1];
}output_t;
typedef struct _device_
{
uint8_t channl;
uint8_t protocol;
uint8_t status;
uint8_t in_index;
uint8_t try_times;
uint8_t out_pending;
uint8_t out_index;
uint8_t ErrCode;
uint8_t continue_err;
uint8_t max_coutinue;
uint16_t ErrCount;
uint16_t PackId;
uint32_t group_start_time;
uint32_t next_scan_time;
uint32_t send_req_time;
uint32_t revice_resp_time;
uint8_t *txbuf;
int txbuf_size;
int (*write)(uint8*, int);
uint8_t *in_err_cnt;
input_t *in;
output_t *out;
void *ext;
}device_t;
typedef struct _send_
{
uint8_t device_id;
uint8_t sn;
uint8_t packet_index;
uint8_t try_times;
uint16_t address;
uint16_t length;
uint32_t next_try_time;
}send_t;
extern int ModbusM_init(void);
extern int ModbusMastertRx(MODBUS_MASTERT_T *m,uint8 *rxbuf, uint8 len);
extern void ModbusMastertPoll(MODBUS_MASTERT_T *m);
extern int zb_ModBusWordWriteHook(unsigned short addr, unsigned short length);
#endif

View File

@ -1,9 +1,13 @@
#include <string.h> #include <string.h>
// #include "driver/ledc.h"
// #include "esp_err.h"
#include "esp_log.h"
#include "ModbusS.h" #include "ModbusS.h"
#include "gwordvar.h" #include "config.h"
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#include <string.h>
#include "esp_log.h"
#include "config.h"
static const char *TAG = "main"; static const char *TAG = "main";
@ -104,58 +108,70 @@ int isBitHI(uint16_t Add)
void ModBusBitWriteHook(uint16_t addr, uint16_t length) void ModBusBitWriteHook(uint16_t addr, uint16_t length)
{ {
} }
extern void reset_depth(void);
// extern void reset_depth(void); uint16_t reboot_req ;
// uint16_t reboot_req ;
// extern uint16_t last_pile_id; // extern uint16_t last_pile_id;
// extern int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length); extern uint16_t *cur_pile_id;
extern int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length);
void ModBusWordWriteHook(uint16_t addr, uint16_t length) void ModBusWordWriteHook(uint16_t addr, uint16_t length)
{ {
// // ESP_LOGI(TAG, "ModBusWordWriteHook"); // ESP_LOGI(TAG, "ModBusWordWriteHook");
// if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){ if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){
// reset_depth(); // reset_depth();
// gWordVar[RECORD_REG_ADDR] = 0; gWordVar[RECORD_REG_ADDR] = 0;
// } }
// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){ if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){
// config_load(); config_load();
// gWordVar[DEPTH_RESET_ADDR] = 0; gWordVar[DEPTH_RESET_ADDR] = 0;
// } }
// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){ if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){
// gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号 gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号
// reset_depth(); // reset_depth();
// gWordVar[DEPTH_RESET_ADDR] = 0; gWordVar[DEPTH_RESET_ADDR] = 0;
// } }
// if(addr == LAST_PILE_ID_ADDR){ if(addr == LAST_PILE_ID_ADDR){
// last_pile_id = gWordVar[LAST_PILE_ID_ADDR]; *cur_pile_id = gWordVar[LAST_PILE_ID_ADDR];
// } }
// else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){ else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){
// save_flow_cfg(); save_flow_cfg();
// } }
// else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){ else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){
// save_depth_cfg(); save_depth_cfg();
// } }
// else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){ else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){
// save_cal_4_20ma(); save_cal_4_20ma();
// } }
// else if(addr == REBOOT_REW_ADDR ){ // else if(addr >= FLOW_CONFIG_ADDR && addr < (FLOW_CONFIG_ADDR + sizeof(flow_config_t))/* && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa */){
// if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){ // save_flow_cfg();
// reboot_req = 0x55aa; // }
// } // else if(addr >= DEPTH_CONFIG_ADDR && addr < (DEPTH_CONFIG_ADDR + sizeof(depth_config_t))){
// else if(gWordVar[REBOOT_REW_ADDR] == 0x55ab){ // save_depth_cfg();
// esp_restart(); // }
// } // else if(addr >= CAL_4_20MA_ADDR && addr < (CAL_4_20MA_ADDR + sizeof(cal_4_20ma_t))){
// else if(gWordVar[REBOOT_REW_ADDR] == 0xaa55){ // save_cal_4_20ma();
// restore_default(); // }
// esp_restart(); else if(addr == REBOOT_REW_ADDR ){
// } if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){
// } reboot_req = 0x55aa;
// else{ }
// zb_ModBusWordWriteHook(addr,length); else if(gWordVar[REBOOT_REW_ADDR] == 0x55ab){
// } esp_restart();
}
else if(gWordVar[REBOOT_REW_ADDR] == 0xaa55){
restore_default();
esp_restart();
}
}
else{
zb_ModBusWordWriteHook(addr,length);
}
} }
extern volatile int modbus_save_flg;
uint16_t modbus_addr = 1;
int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc) int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc)
{ {
// ESP_LOGI(TAG, "ModbusSlaveProcess");
uint16_t crcData,crcChk; uint16_t crcData,crcChk;
uint8_t Offset,ByteAdd; uint8_t Offset,ByteAdd;
uint16_t ByteNumber; uint16_t ByteNumber;
@ -171,7 +187,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
} }
/*地址校验*/ /*地址校验*/
if((rxbuf[0]==MODBUS_SALVE_ADDRESS) || (rxbuf[0]==255)){ if((rxbuf[0]==modbus_addr) || (rxbuf[0]==255)){
/*crc校验*/ /*crc校验*/
if(is_crc != 0){ if(is_crc != 0){
@ -212,6 +228,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
break; break;
case 0x03: case 0x03:
case 0x04: //Read Holding Registers case 0x04: //Read Holding Registers
// ESP_LOGI(TAG, "read");
if((add+length) > gWORD_SIZE) if((add+length) > gWORD_SIZE)
{ {
txbuf[1] = 0x80 + rxbuf[1]; txbuf[1] = 0x80 + rxbuf[1];
@ -270,6 +287,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
out_len = 6; out_len = 6;
break; break;
case 0x06: //Write Single Register case 0x06: //Write Single Register
// ESP_LOGI(TAG, "write");
// ESP_LOGI(TAG, "modbus 0x06"); // ESP_LOGI(TAG, "modbus 0x06");
if(add >= gWORD_SIZE) if(add >= gWORD_SIZE)
{ {
@ -279,7 +297,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
break; break;
} }
gWordVar[add] = (rxbuf[4]<<8)+rxbuf[5]; gWordVar[add] = (rxbuf[4]<<8)+rxbuf[5];
// ESP_LOGI(TAG, "gWordVar[%d]=0x%04x", add, gWordVar[add]); ESP_LOGI(TAG, "gWordVar[%d]=0x%04x", add, (rxbuf[4]<<8)+rxbuf[5]);
// ESP_LOGI(TAG, "%d %d", depth_config->input_type, depth_config->port); // ESP_LOGI(TAG, "%d %d", depth_config->input_type, depth_config->port);
memcpy(txbuf,rxbuf,6); memcpy(txbuf,rxbuf,6);
ModBusWordWriteHook(add,1); ModBusWordWriteHook(add,1);

46
main/stm32/ModbusS.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef _MODBUS_H
#define _MODBUS_H
#include<stdint.h>
//#define uint8_t unsigned char
//#define uint16_t unsigned short
//#define uint32 unsigned int
#define setBit(Add) gBitVar[(Add)>>3] |= (1<<((Add)&0x07))
#define clrBit(Add) gBitVar[(Add)>>3] &= ~(1<<((Add)&0x07))
//#define ModBusTxData uart1_tx
extern uint16_t crc16(uint8_t *puchMsg, uint16_t usDataLen);
extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc);
int isBitHI(uint16_t Add);
void xorBit(uint16_t Add);
void WriteBit(uint16_t Add,uint8_t bit_value);
#define gBIT_SIZE 128
#define gWORD_SIZE 1024
extern uint8_t gBitVar[(gBIT_SIZE+7)/8];
extern uint16_t gWordVar[gWORD_SIZE];
extern uint16_t modbus_addr;
// #include "usart.h"
// #include "gpio.h"
// #include "main.h"
#define BUFFER_SIZE 2000
extern uint8_t rx_buffer[256];
extern uint8_t tx_buffer[256];
extern uint16_t rx_buff_len;
// extern __IO uint8_t recv_end_flag;
extern uint8_t recv_end_flag;
extern void modbus_recv_mode(void);
extern void usart2_dma_recv_start(void);
extern void modbus_send(uint8_t *buf, uint8_t len);
// extern void save_flow_cfg(void);
extern int check_mastrt_recv(void);
void ModBusWordWriteHook(uint16_t addr, uint16_t length);
#endif

426
main/stm32/ads1220.c Normal file
View File

@ -0,0 +1,426 @@
#include "ads1220.h"
// #include "main.h"
#include "config.h"
#include "ModbusS.h"
#include "ModbusM.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "utils.h"
#include "config.h"
#include "driver/mcpwm.h"
#include "depth.h"
#include "led.h"
#define TAG "ADS1220"
static spi_device_handle_t spi2;
QueueHandle_t ads1220_drdy_queue = NULL;
const uint8_t ch_cmd[4] = {0x0C, 0xA1, 0x0C, 0xB1};
int ad_value[4];
uint32_t ad_update_time[4];
extern flow_t *pflow;
static int ch = 0;
void ADS1220_Init(void)
{
// ESP_LOGI(TAG, "Start init ADS1220.\n");
ADS1220_Config();
// ESP_LOGI(TAG, "Start ADS1220_Config.\n");
ch = 0;
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[0]);
ADS1220_WriteCommand(ADS1220_CMD_START);
}
static void IRAM_ATTR ads1220_done_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig,
const cap_event_data_t *edata, void *arg)
{
// uint32_t gpio_num = (uint32_t)arg;
// if (ch == 1)
// {
// pflow[0].update_time = xTaskGetTickCount();
// }
// if (ch == 3)
// {
// pflow[1].update_time = xTaskGetTickCount();
// }
// ESP_LOGI(TAG, "ads done");
ad_update_time[ch] = edata->cap_value;
xQueueSendFromISR(ads1220_drdy_queue, &ad_update_time[ch], NULL);
}
static void GPIO_Init(void)
{
// interrupt of rising edge
// io_conf.intr_type = GPIO_INTR_NEGEDGE;
// // bit mask of the pins, use GPIO4/5 here
// io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
// // set as input mode
// io_conf.mode = GPIO_MODE_INPUT;
// // enable pull-up mode
// io_conf.pull_up_en = 1;
// gpio_config(&io_conf);
// change gpio intrrupt type for one pin
// gpio_set_intr_type(GPIO_INPUT_IO_39, GPIO_INTR_NEGEDGE);
// create a queue to handle gpio event from isr
ads1220_drdy_queue = xQueueCreate(1, sizeof(uint32_t));
// install gpio isr service
// gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
// // hook isr handler for specific gpio pin
// gpio_isr_handler_add(GPIO_INPUT_IO_39, gpio_isr_handler, (void *)GPIO_INPUT_IO_39);
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, GPIO_INPUT_IO_39));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_INPUT_IO_39));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = ads1220_done_handler, // 绑定深度中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf));
}
uint8_t ret = 0;
/****
* ADS1220<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD>
**/
u8 ADS1220_ReadReg(u8 reg)
{
u8 Val;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RREG | ((reg & 0x03) << 2);
t.length = 2 * 8;
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = t.rx_data[1];
return Val;
}
/***
* <EFBFBD><EFBFBD>ADS1220<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>24Bits
*
**/
// static u32 ADS1220_ReadWrite24Bits(u32 dat)
// {
// uint8_t tmp[3];
// static int val = 0;
// HAL_SPI_TransmitReceive(&spi2, (uint8_t *)&dat, (uint8_t *)tmp, 3, 500);
// val = ((uint32_t)tmp[0] << 16) + ((uint32_t)tmp[1] << 8) + ((uint32_t)tmp[2] << 0);
// // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ 23λ <20><>1 <20><>Ϊ <20>з<EFBFBD><D0B7><EFBFBD>
// if (val & 0x800000)
// {
// val |= 0xFF000000;
// }
// return val;
// }
// ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
s32 ADS1220_ReadData(void)
{
s32 Val = 0;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.tx_data[0] = ADS1220_CMD_RDATA;
t.length = 4 * 8; // Command is 24 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
Val = (t.rx_data[1] << 16) | (t.rx_data[2] << 8) | t.rx_data[3];
if (Val & 0x800000)
{
Val |= 0xFF000000;
}
return Val;
}
// ADS1220д<30>Ĵ<EFBFBD><C4B4><EFBFBD>
void ADS1220_WriteReg(u8 reg, u8 dat)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
// t.flags = SPI_TRANS_USE_TXDATA;
t.tx_data[0] = ADS1220_CMD_WREG | ((reg & 0x03) << 2);
t.tx_data[1] = dat;
t.length = 2 * 8; // Command is 16 bits
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
assert(ret == ESP_OK);
}
// ADS1220д<30><D0B4><EFBFBD><EFBFBD>
void ADS1220_WriteCommand(u8 cmd)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.length = 8 * 2; // Command is 8 bits
t.tx_data[0] = cmd; // The data is the cmd itself
// ESP_LOGI(TAG, "spi_device_polling_transmit befor.\n");
ret = spi_device_polling_transmit(spi2, &t); // Transmit!
// ESP_LOGI(TAG, "spi_device_polling_transmit after.\n");
assert(ret == ESP_OK);
// // ADS1220_CS=0;
// ADS1220_nCS_LOW();
// ADS1220_ReadWriteByte(cmd);
// // ADS1220_CS=1;
// ADS1220_nCS_HIGH();
}
// ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
void ADS1220_PowerDown(void)
{
ADS1220_WriteCommand(ADS1220_CMD_POWERDOWN); //
}
// ADS1220<32><30><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
void ADS1220_StartConv(u8 channal)
{
/*
u8 val ;
val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220.CurrentCH = ADS1220_Channal1;
val = val & 0x0f | Channal1;
ADS1220_WriteReg(ADS1220_REG0, val ); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>0 <20><><EFBFBD><EFBFBD>: AIN P = AIN0, AIN N = AIN1 <20><><EFBFBD>ģʽ ʹ<><CAB9>PGA 64 (110) <20><><EFBFBD><EFBFBD>PGA (0)
*/
ADS1220_WriteCommand(ADS1220_CMD_START); // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
}
// ADS1220<32><30>λ
void ADS1220_Reset(void)
{
ADS1220_WriteCommand(ADS1220_CMD_RESET); // <20><>λADS1220
}
// ADS1220 PGA<47><41><EFBFBD><EFBFBD>
void ADS1220_PGASet(u8 gain)
{
u8 val;
val = ADS1220_ReadReg(ADS1220_REG0);
val = (val & 0xF1) | gain;
ADS1220_WriteReg(ADS1220_REG0, val);
// val = ADS1220_ReadReg(ADS1220_REG0);
ADS1220_StartConv(ADS1220_Channal1); // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
}
// static uint8_t dara_rate = 0x40;
void ADS1220_Config(void)
{
static uint8_t read[4];
ADS1220_WriteCommand(ADS1220_CMD_RESET); // <20><>λADS1220
vTaskDelay(10);
// ESP_LOGI(TAG, "ADS1220_WriteCommand.\n");
ADS1220_WriteReg(ADS1220_REG0, 0xa0); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>0 <20><><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD>: AIN P = AIN0, AIN N = AVSS <20><><EFBFBD><EFBFBD>ģʽ ʹ<><CAB9>PGA1 (100) <20><><EFBFBD><EFBFBD>PGA(0)
ADS1220_WriteReg(ADS1220_REG1, 0x20); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>1 <20><><EFBFBD><EFBFBD>: Turboģʽ 40.SPS(00000)<29><>ʹ<EFBFBD><CAB9><EFBFBD>¶ȴ<C2B6><C8B4><EFBFBD><EFBFBD><EFBFBD>(0) <20>رյ<D8B1><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(0)
ADS1220_WriteReg(ADS1220_REG2, 0x20); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>2 <20><><EFBFBD><EFBFBD>: <20><>ѹ<EFBFBD><D1B9>׼ <20>ڲ<EFBFBD>2.048-v<>ο<EFBFBD>(00) ʹ<><CAB9>оƬFIR<49>˲<EFBFBD>50Hz(10) <20><><EFBFBD><EFBFBD>Դ0ma // Low-side<64><65>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD> Ĭ<><C4AC>(0) <20><><EFBFBD><EFBFBD>Դ <20>ر<EFBFBD>
ADS1220_WriteReg(ADS1220_REG3, 0x00); // <20>Ĵ<EFBFBD><C4B4><EFBFBD>3 <20><><EFBFBD><EFBFBD>: : IDAC1 connect to AIN2 : IDAC2 disabled
read[0] = ADS1220_ReadReg(ADS1220_REG0);
read[1] = ADS1220_ReadReg(ADS1220_REG1);
read[2] = ADS1220_ReadReg(ADS1220_REG2);
read[3] = ADS1220_ReadReg(ADS1220_REG3);
printf("ads1220 reg %02x %02x %02x %02x \n", read[0], read[1], read[2], read[3]);
}
static void SPI2_Init(void)
{
esp_err_t ret;
spi_bus_config_t buscfg2 = {
.miso_io_num = SPI2_PIN_NUM_MISO,
.mosi_io_num = SPI2_PIN_NUM_MOSI,
.sclk_io_num = SPI2_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 8};
spi_device_interface_config_t devcfg2 = {
.clock_speed_hz = 1 * 1000 * 1000, // Clock out at 1 MHz
.mode = 0, // SPI mode 0
.cs_ena_posttrans = 2, // Keep the CS low 2 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than SPI CLK
.spics_io_num = SPI2_PIN_NUM_CS, // CS pin
.queue_size = 1, // We want to be able to queue 7 transactions at a time
// .address_bits = 8,
// .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line
// .command_bits = 8,
};
// Initialize the SPI bus
ret = spi_bus_initialize(ADS1220_HOST, &buscfg2, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
// Attach the ADS1220 to the SPI bus
ret = spi_bus_add_device(ADS1220_HOST, &devcfg2, &spi2);
ESP_ERROR_CHECK(ret);
}
extern void zero_totalflow(int ch);
extern int zero_totalflow_req;
extern int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time);
extern cal_4_20ma_t *cal_4_20ma;
extern flow_config_t *flow_config;
extern flow_t *pflow;
extern int flow_rem[2];
void ads1220_task(void)
{
uint32_t io_num;
// static uint32_t ad_flow_tick = 10;
while (1)
{
// ESP_LOGI(TAG, "xQueueReceive before\n ");
if (xQueueReceive(ads1220_drdy_queue, &io_num, 200))
{
int ad_ch;
int ad_raw = ADS1220_ReadData();
// if (ch == 3)
// ESP_LOGI(TAG, "ads1220 ch3 ad_rad:%d", (int)ad_raw);
ad_value[ch] = ad_raw / 128;
ad_ch = ch;
gWordVar[AD_RAW_REG_ADDR + ch] = ad_value[ch] / 2;
// ESP_LOGI(TAG, "channel : %d ad_value: %d\n ", ch, ad_value[ch]);
ch++;
if (ch >= sizeof(ch_cmd))
{
ch = 0;
}
ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ch]);
ADS1220_WriteCommand(ADS1220_CMD_START);
if (ad_ch == 1)
LED_Toggle(LED2_GPIO_PIN);
int flow_ch = ad_ch / 2;
if ((ad_ch == 1 || ad_ch == 3) && flow_config->input_type == 1)
{
if ((depth_data->pile_work_state_and_direction & 0xff00) != PILE_STATE_WORK)
{
// ESP_LOGI(TAG, "not work");
goto out;
}
int time_diff = abs_sub(ad_update_time[ad_ch], pflow[flow_ch].update_time);
ad_flow_cal_t *cal = flow_config->ad_cal;
int t_flow; // time_diff时间段总流量
pflow[flow_ch].flow_ = scale(ad_value[ad_ch], cal_4_20ma->ch[flow_ch].ad_4ma, cal_4_20ma->ch[flow_ch].ad_20ma, cal[flow_ch].flow_min, cal[flow_ch].flow_max);
if (pflow[flow_ch].flow_ < flow_config->min_flow[flow_ch]) // 小流量切除
{
pflow[flow_ch].flow = 0;
}
else
{
pflow[flow_ch].flow = pflow[flow_ch].flow_;
}
if (pflow[flow_ch].update_time == 0) goto out; // 首次无法计算时间差
// 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为1us
// flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s
// t_diff = time_diff / 1000 将时间差换算成秒
// t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL
// 取出0.01L的整数部分累加,余数部分和下次值累加
// t_flow = pflow[i].flow * 1000 * time_diff / 1000000 / 60;
int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000);
// if (ad_ch == 1) ESP_LOGI(TAG, "time_diff_us:%d", time_diff_us);
t_flow = pflow[flow_ch].flow * (long long)time_diff_us / 60 / 100; //(5 * 60);
// ESP_LOGI(TAG, "sub:%d total:%d", sub_flow, (int)pflow[flow_ch].total_flow);
flow_rem[flow_ch] += t_flow;
int sub_flow = flow_rem[flow_ch] / 10000;
// ESP_LOGI(TAG, "sub:%d total:%d", sub_flow, (int)pflow[flow_ch].total_flow);
pflow[flow_ch].total_flow += sub_flow;
flow_rem[flow_ch] = flow_rem[flow_ch] - sub_flow * 10000;
out:
pflow[flow_ch].update_time = ad_update_time[ad_ch];
// if (ad_ch == 1) ESP_LOGI(TAG, "flow:%d total_flow:%d", (int)pflow[flow_ch].flow, (int)pflow[flow_ch].total_flow);
// ESP_LOGI(TAG, "(type1) flow_rem[%d].flow: %u time_diff=%d", flow_ch ,pflow[flow_ch].flow,time_diff);
// ESP_LOGI(TAG, "ads1220 ch:%d time_diff:%d flow:%d total_flow:%d", flow_ch, time_diff, pflow[flow_ch].flow, pflow[flow_ch].total_flow);
}
}
else
{
ESP_LOGI(TAG, "wait queue failed");
ADS1220_Init();
}
}
}
void zero_flow1(void)
{
memset(pflow, 0, sizeof(flow_t) * 2);
for (int i = 0; i < 2; i++)
{
flow_rem[i] = 0;
}
}
void ads1220_task_start(void)
{
SPI2_Init();
GPIO_Init();
ADS1220_Init();
xTaskCreate(ads1220_task, "ads1220_task", 4096, NULL, 10, NULL);
}
// void ADS1220_set_rate(int i)
//{
// switch (i)
// {
// case 1 :dara_rate = 0x00;//20SPS
// break;
// case 2 :dara_rate = 0x20;//45SPS
// break;
// case 3 :dara_rate = 0x40;//90SPS
// break;
// case 4 :dara_rate = 0x60;//175SPS
// break;
// default:dara_rate = 0x00;//20SPS
// break;
// }
// }
// int ADS1220_get_rate(void)
//{
// switch (dara_rate)
// {
// case 0x00 :return 20*100;//20SPS
// break;
// case 0x20 :return 45*100;//45SPS
// break;
// case 0x40 :return 90*100;//90SPS
// break;
// case 0x60 :return 175*100;//175SPS
// break;
// default:return 20*100;//20SPS
// break;
// }
// }
// ch0 0.5V 3478
// ch0 1.0V 0
// ch0 1.5V 10429
// ch1 4.000ma 12783
// ch1 12.00ma 38349
// ch2 4.000ma 12764
// ch2 12.00ma 38336

110
main/stm32/ads1220.h Normal file
View File

@ -0,0 +1,110 @@
#ifndef __ADS1220_H
#define __ADS1220_H
// #include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
typedef uint8_t u8;
typedef uint32_t u32;
typedef int32_t s32;
#define ADS1220_HOST SPI2_HOST
#define SPI2_PIN_NUM_MISO 6
#define SPI2_PIN_NUM_MOSI 5
#define SPI2_PIN_NUM_CLK 16
#define SPI2_PIN_NUM_CS 15
#define PARALLEL_LINES 16
#define ADS1220_nCS_HIGH() gpio_set_level(GPIO_NUM_38, 1)
#define ADS1220_nCS_LOW() gpio_set_level(GPIO_NUM_38, 0)
#define ADS1220_CMD_WREG 0x40
#define ADS1220_CMD_RREG 0x20
#define ADS1220_CMD_RESET 0x06
#define ADS1220_CMD_START 0x08
#define ADS1220_CMD_POWERDOWN 0x02
#define ADS1220_CMD_RDATA 0x10
#define Channal1 0x00
#define Channal2 0x10
#define Channal3 0x20
#define Channal4 0x30
#define ADS1220_REG0 0x00
#define ADS1220_REG1 0x01
#define ADS1220_REG2 0x02
#define ADS1220_REG3 0x03
#define PGAGain1 0x00
#define PGAGain2 0x02
#define PGAGain4 0x04
#define PGAGain8 0x06
#define PGAGain16 0x08
#define PGAGain32 0x0A
#define PGAGain64 0x0C
#define PGAGain128 0x0E
#define ADS1220_Standby 0
#define ADS1220_ConvStart 1
#define ADS1220_ConvFinish 2
#define ADS1220_Channal1 0
#define ADS1220_Channal2 1
#define ADS1220_Channal3 2
#define ADS1220_Channal4 3
#define GPIO_INPUT_IO_39 7
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_39)
#define ESP_INTR_FLAG_DEFAULT 0
typedef struct
{
int ch0_4ma;
int ch0_12ma;
float ch0_4ma_yl;
float ch0_12ma_yl;
int ch1_4ma;
int ch1_12ma;
float ch1_4ma_yl;
float ch1_12ma_yl;
int ch2_4ma;
int ch2_12ma;
float ch2_4ma_yl;
float ch2_12ma_yl;
}ads_cali_t;
//extern ads_cali_t ads_cali;
uint32_t get_now_20us(void);
int32_t tim_diff(uint32_t a,uint32_t b);
int ADS1220_get_rate(void);
void ADS1220_set_rate(int i);
void ADS1220_Init(void); // ADS1220<32><30>ʼ<EFBFBD><CABC>
void ADS1220_Config(void); // ADS1220<32><30><EFBFBD><EFBFBD>
void ADS1220_StartConv(u8 channal); // ADS1220<32><30><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
void ADS1220_Reset(void); // ADS1220<32><30>λ
void ADS1220_PowerDown(void); // ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
void ADS1220_PGASet(u8 gain); // ADS1220 PGA<47><41><EFBFBD><EFBFBD>
void ADS1220_WriteCommand(u8 cmd); // ADS1220д<30><D0B4><EFBFBD><EFBFBD>
s32 ADS1220_ReadData(void); // ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ADS1220_WriteReg(u8 reg,u8 dat); // ADS1220д<30>Ĵ<EFBFBD><C4B4><EFBFBD>
u8 ADS1220_ReadReg(u8 reg); // ADS1220<32><30><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
u8 ADS1220_ReadWriteByte(u8 dat); // <20><>SPI<50><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>һ<EFBFBD>ֽ<EFBFBD>
u32 ADS1220_ReadWrite24Bits(u32 dat); // <20><>ADS1220<32><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>24Bits
void zero_flow1(void);
int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max);
#endif

View File

@ -1,3 +1,11 @@
#include "bl0939.h"
#include "string.h"
#include "utils.h"
// #include "ModbusS.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@ -5,16 +13,21 @@
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h" #include "esp_log.h"
#include "pile_id.h"
#include "bl0939.h"
#include "depth.h"
#include "gwordvar.h"
#include "utils.h"
#define TAG "BL0939" #define TAG "BL0939"
#define BL0939_HOST SPI3_HOST
#define SPI1_PIN_NUM_MISO 37
#define SPI1_PIN_NUM_MOSI 36
#define SPI1_PIN_NUM_CLK 35
#define SPI1_PIN_NUM_CS 40
extern move_t *pMoveCtx;
static spi_device_handle_t spi1; static spi_device_handle_t spi1;
move_t *pMoveCtx = (move_t *)&gWordVar[MOVE_REG_ADDR];
static void SPI1_Init(void) static void SPI1_Init(void)
{ {
@ -241,11 +254,13 @@ void BL0939_task()
} }
if (gWordVar[AC_CURRENT_REG_ADDR + move_current_channel] > depth_config->current_on_threshold) if (gWordVar[AC_CURRENT_REG_ADDR + move_current_channel] > depth_config->current_on_threshold)
{ {
if (++pMoveCtx->time_count > depth_config->move_on_duratino) if (++pMoveCtx->time_count > depth_config->move_on_duratino) // 时间单位和采样时间有关100ms
{ {
pMoveCtx->status = 1; pMoveCtx->status = 1;
pMoveCtx->time_count = 0; pMoveCtx->time_count = 0;
pMoveCtx->work_time = 0;
pMoveCtx->pile_inc_req = 1; pMoveCtx->pile_inc_req = 1;
pMoveCtx->work_stop_state_flag = 0;
// ESP_LOGI(TAG, "cur > th, status trun to on"); // ESP_LOGI(TAG, "cur > th, status trun to on");
} }
@ -254,18 +269,22 @@ void BL0939_task()
else if (pMoveCtx->status == 1) else if (pMoveCtx->status == 1)
{ {
// ESP_LOGI(TAG, "mov status is on"); // ESP_LOGI(TAG, "mov status is on");
pMoveCtx->work_time++;
int move_current_channel = depth_config->move_current_channel; int move_current_channel = depth_config->move_current_channel;
if (move_current_channel > 2 || move_current_channel < 0) if (move_current_channel > 2 || move_current_channel < 0)
{ {
move_current_channel = 2; move_current_channel = 2;
} }
if (gWordVar[AC_CURRENT_REG_ADDR + 2] < depth_config->current_off_threshold) if (gWordVar[AC_CURRENT_REG_ADDR + move_current_channel] < depth_config->current_off_threshold)
{ {
if (++pMoveCtx->time_count > depth_config->move_off_duration) if (++pMoveCtx->time_count > depth_config->move_off_duration)
{ {
pMoveCtx->status = 0; pMoveCtx->status = 0;
pMoveCtx->time_count = 0; pMoveCtx->time_count = 0;
if (pMoveCtx->work_time >= CURRENT2_TIMEOUT_TH)
{
pMoveCtx->work_stop_state_flag = 1;
}
// ESP_LOGI(TAG, "cur > th, status trun to off"); // ESP_LOGI(TAG, "cur > th, status trun to off");
} }
} }

31
main/stm32/bl0939.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef BL0939_H__
#define BL0939_H__
// #include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
void bl0939_reset(void);
int bl0939_get_current_A(void);
int bl0939_get_current_B(void);
int bl0939_get_voltage(void);
//DMA
void bl0939_get_abv(uint8_t * buf);
int bl0939_parse_abv(uint8_t * buf,unsigned int * data);
#endif

153
main/stm32/capture.c Normal file
View File

@ -0,0 +1,153 @@
/*
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "driver/mcpwm.h"
#include "driver/gpio.h"
const static char *TAG = "capture";
typedef struct capture_event
{
int ch;
uint32_t val;
} capture_event_t;
#define FLOW1_PIN_ECHO GPIO_NUM_39 // 捕获GPIO端口
#define FLOW2_PIN_ECHO GPIO_NUM_38 // 捕获GPIO端口
#define TRIGGER_THREAD_PRIORITY 5
typedef struct
{
uint32_t capture_signal;
mcpwm_capture_signal_t sel_cap_signal;
} capture;
static uint32_t cap_val_begin_of_flow1 = 0;
static uint32_t cap_val_end_of_flow1 = 0;
static uint32_t cap_val_begin_of_flow2 = 0;
static uint32_t cap_val_end_of_flow2 = 0;
// static xQueueHandle cap_queue;
extern uint32_t rtc_clk_apb_freq;
uint32_t volatile t15_ccr[2];
uint16_t volatile t15_ccr_times[2];
static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
cap_val_end_of_flow1 = edata->cap_value;
capture_event_t cap_event = {.val = 0, .ch = 1};
cap_event.val = cap_val_end_of_flow1 - cap_val_begin_of_flow1;
t15_ccr_times[0] = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
t15_ccr[0]++;
return high_task_wakeup == pdTRUE;
}
void capture_flow1_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pullup_en(FLOW1_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf));
mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_1, 1000000);
int value = mcpwm_capture_signal_get_value(MCPWM_UNIT_1, MCPWM_SELECT_CAP1);
ESP_LOGI(TAG, "capture_flow_init value=%d", value);
}
static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
cap_val_end_of_flow2 = edata->cap_value;
capture_event_t cap_event = {.val = 0, .ch = 2};
cap_event.val = cap_val_end_of_flow2 - cap_val_begin_of_flow2;
t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
t15_ccr[1]++;
// send measurement back though queue
// xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
void capture_flow2_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf));
mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_2, 1000000);
// ESP_LOGI(TAG, "capture_flow_init");
}
// void capture_task(void)
// {
// while (true) {
// capture_event_t cap_event = {.val = 0, .ch = 1};
// uint32_t pulse_width_us = 0;
// // block and wait for new measurement
// // ESP_LOGI(TAG, "xQueueReceive started");
// xQueueReceive(cap_queue, &cap_event, portMAX_DELAY);
// // ESP_LOGI(TAG, "xQueueReceive after");
// // ESP_LOGI(TAG, " cap_event.val: %d, cap_event.ch : %d", cap_event.val, cap_event.ch);
// switch (cap_event.ch)
// {
// case 1: //flow1 capture
// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
// ESP_LOGI(TAG, " (flow1 capture) Pulse width: %uus", pulse_width_us);
// break;
// case 2: //flow2 capture
// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
// ESP_LOGI(TAG, "(flow2 capture) Pulse width: %uus", pulse_width_us);
// break;
// default: ESP_LOGI(TAG, " default\n");
// break;
// }
// }
// }
// void capture_depth_init();
// void pcnt_rotary_encoder_init(void);
void capture_init(void)
{
// cap_queue = xQueueCreate(3, sizeof(capture_event_t));
// if (cap_queue == NULL) {
// ESP_LOGE(TAG, "failed to alloc cap_queue");
// return;
// }
// capture_depth_init();
capture_flow1_init();
capture_flow2_init();
// start gcapture_task
// xTaskCreate(capture_task, "capture_task", 4096, NULL, TRIGGER_THREAD_PRIORITY, NULL);
// ESP_LOGI(TAG, "capture_task started");
// pcnt_rotary_encoder_init();
}

104
main/stm32/comm.c Normal file
View File

@ -0,0 +1,104 @@
#include "stdlib.h"
#include "utils.h"
#include "fram.h"
#include "ModbusS.h"
#include "ads1220.h"
// #include "SEGGER_RTT.h"
#include "ModbusM.h"
extern void modbus_master_poll(int n);
extern int modbus_master_on_revice(int ch, uint8_t *rxbuf, int length);
extern uint8_t uart1_txbuf[];
extern uint8_t uart1_rxbuf[];
extern uint8_t uart2_txbuf[];
extern uint8_t uart2_rxbuf[];
extern int uart1_rx_start(void);
extern int uart1_rx_check(void);
extern int uart1_tx_start(uint8_t *data, int length);
extern int uart2_rx_start(void);
extern int uart2_rx_check(void);
extern int uart2_tx_start(uint8_t *data, int length);
void RS485_init();
void print_init();
extern uint8_t led_toggle_count;
void comm_poll(void)
{
static uint32_t modbus_master_tick = 0;
static uint32_t tick_100ms = 0;
static int uart1_timeout = 0;
static int uart2_timeout = 0;
int rxlen,txlen;
// if((rxlen = uart1_rx_check()) > 0){
// txlen = ModbusSlaveProcess(uart1_txbuf,uart1_rxbuf,rxlen,1);
// if(txlen > 0)
// {
// HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
// uart1_tx_start(uart1_txbuf,txlen);
// }
// else{
// uart1_rx_start();
// }
// }
if((rxlen = uart2_rx_check()) > 0){
txlen = ModbusSlaveProcess(uart2_txbuf,uart2_rxbuf,rxlen,1);
if(txlen > 0)
{
uart2_tx_start(uart2_txbuf,txlen);
}
else{
uart2_rx_start();
}
led_toggle_count = 0;
uart1_timeout = 0;
}
if(TickDiff(tick_100ms) > 100)
{
tick_100ms = xTaskGetTickCount();
if(++uart1_timeout > 100){
uart1_timeout = 0;
// HAL_UART_MspDeInit(&huart2);
// MX_USART2_UART_Init();
uart2_rx_start();
}
if(++uart2_timeout > 1000){
uart2_timeout = 0;
// HAL_UART_MspDeInit(&huart1);
// MX_USART1_UART_Init();
}
}
if(TickDiff(modbus_master_tick) > 10)
{
modbus_master_tick = xTaskGetTickCount();
modbus_master_poll(0);
}
if((rxlen = uart1_rx_check()) > 0){ // 做一个uart1_rx_check 读串口
modbus_master_on_revice(0,uart1_rxbuf,rxlen);
uart2_timeout = 0;
}
}
void comm_init(void)
{
// MX_USART1_UART_Init();
// MX_USART2_UART_Init();
RS485_init();
print_init();
ModbusM_init();
uart2_rx_start();
}

View File

@ -1,18 +1,21 @@
#include <string.h>
#include "esp_log.h"
#include "config.h" #include "config.h"
#include "fram.h" #include "fram.h"
#include "flow.h" #include "utils.h"
#include "depth.h" #include "modbuss.h"
#include "stdint.h"
#include "esp_log.h"
// #include "flow.h"
// #include "depth.h"
// config_data_t * config_para = (config_data_t*)&gWordVar[256];
// extern real_t * real;
static const char *TAG = "config"; static const char *TAG = "config";
extern cal_4_20ma_t *cal_4_20ma; //电流数据结构体 extern cal_4_20ma_t *cal_4_20ma;//电流数据结构体
extern flow_config_t *flow_config; //流量数据结构体 extern flow_config_t *flow_config;//流量数据结构体
extern depth_config_t *depth_config; //深度数据结构体 extern depth_config_t *depth_config;//深度数据结构体
extern float ac_current_coef[3]; //可能表示交流电电流的系数或校准参数 ? extern float ac_current_coef[3];//可能表示交流电电流的系数或校准参数 ?
// 三标一号机 // 三标一号机
const cal_4_20ma_t default_cal_4_20ma = {0, {{12740, 63845}, {12760, 63953}}}; const cal_4_20ma_t default_cal_4_20ma = {0, {{12740, 63845}, {12760, 63953}}};
const flow_config_t default_flow_cfg = {0, 1, {0, 0}, {{0, 10000}, {0, 10000}}, {6944, 6944}}; // 4~20MA 输入6m/H 100.00L/min const flow_config_t default_flow_cfg = {0, 1, {0, 0}, {{0, 10000}, {0, 10000}}, {6944, 6944}}; // 4~20MA 输入6m/H 100.00L/min
@ -48,13 +51,46 @@ const depth_config_t default_depth_cfg = {
.move_on_duratino = 150, .move_on_duratino = 150,
.move_off_duration = 150, .move_off_duration = 150,
.move_current_channel = 2, .move_current_channel = 2,
}; // 方向脉冲编码器 10线2倍频 }; // 方向脉冲编码器 10线2倍频
// const depth_config_t default_depth_cfg = {0,3,0,3800,-200,16000,100,-200}; //200线开漏型正交 // const depth_config_t default_depth_cfg = {0,3,0,3800,-200,16000,100,-200}; //200线开漏型正交
// const depth_config_t default_depth_cfg = {0,1,0,76000,-200,16000,100,-200}; // const depth_config_t default_depth_cfg = {0,1,0,76000,-200,16000,100,-200};
#define MAGIC 30627
#define EE_CAL_4_20MA_ADDR 16
#define EE_FLOW_CFG_ADDR (EE_CAL_4_20MA_ADDR + sizeof(default_cal_4_20ma))
#define EE_DEPTH_CFG_ADDR (EE_FLOW_CFG_ADDR + sizeof(default_flow_cfg))
extern uint16_t *cur_pile_id;
extern void init_comm(void);
// void sys_init(void)
// {
// // HAL_Delay(100);
// // GetCompileDateTime(&gWordVar[0]);
// // flash_load();
// // modbus_addr = config_para->modbus_addr;
// // sliding_window_filter_init(&sliding_window_a,real->data_long,200);
// // HAL_TIM_Base_Start(&htim6);//ms<6D><73>ʱ<EFBFBD><CAB1>
// // HAL_TIM_Base_Start_IT(&htim17);//us<75><73>ʱ<EFBFBD><CAB1>
// //// HAL_TIM_Encoder_Start_IT(&htim1,TIM_CHANNEL_ALL);//enc
// // HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);//enc
// // HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);//ll
// // HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//ll
// // HAL_TIM_IC_Start_IT(&htim15,TIM_CHANNEL_1);//ll
// // HAL_TIM_IC_Start_IT(&htim15,TIM_CHANNEL_2);//ll
// // HAL_UART_Receive_IT(&huart1,&temp_rx_data,1);
// // init_comm();
// // if(config_para->traffic_mode == MA_4_20)
// // {
// // ADS1220_Init();
// // }
// // HAL_GPIO_WritePin(GPS_PWR_EN_GPIO_Port, GPS_PWR_EN_Pin, GPIO_PIN_SET);
// // HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin,0);
// // HAL_Delay(500);
// }
uint16_t last_pile_id = 0;
/*fram_read */ /*fram_read */
/* /*
I2C 线 ESP32 FRAM I2C 线 ESP32 FRAM
@ -69,7 +105,7 @@ void config_load(void)
{ {
if (temp[0] == MAGIC) if (temp[0] == MAGIC)
{ {
last_pile_id = temp[1]; *cur_pile_id = temp[1];
} }
} }
fram_read(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma)); fram_read(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma));
@ -89,7 +125,6 @@ void config_load(void)
} }
ESP_LOGW(TAG, "load flow_cfg:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", (unsigned int)flow_config->magic, (unsigned int)flow_config->input_type, (unsigned int)flow_config->min_flow[0], (unsigned int)flow_config->min_flow[1], (unsigned int)flow_config->ad_cal[0].flow_min, (unsigned int)flow_config->ad_cal[0].flow_max, (unsigned int)flow_config->ad_cal[1].flow_min, (unsigned int)flow_config->ad_cal[1].flow_max, (unsigned int)flow_config->pulse_coef[0], (unsigned int)flow_config->pulse_coef[1]); ESP_LOGW(TAG, "load flow_cfg:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", (unsigned int)flow_config->magic, (unsigned int)flow_config->input_type, (unsigned int)flow_config->min_flow[0], (unsigned int)flow_config->min_flow[1], (unsigned int)flow_config->ad_cal[0].flow_min, (unsigned int)flow_config->ad_cal[0].flow_max, (unsigned int)flow_config->ad_cal[1].flow_min, (unsigned int)flow_config->ad_cal[1].flow_max, (unsigned int)flow_config->pulse_coef[0], (unsigned int)flow_config->pulse_coef[1]);
#if 1
fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
if (depth_config->magic != MAGIC) if (depth_config->magic != MAGIC)
{ {
@ -102,7 +137,14 @@ void config_load(void)
(unsigned int)depth_config->sample_depth, (unsigned int)depth_config->depth_offset, (unsigned int)depth_config->min_valid_depth, \ (unsigned int)depth_config->sample_depth, (unsigned int)depth_config->depth_offset, (unsigned int)depth_config->min_valid_depth, \
(unsigned int)depth_config->inc_pile_depth, (unsigned int)depth_config->current_on_threshold, (unsigned int)depth_config->current_off_threshold, \ (unsigned int)depth_config->inc_pile_depth, (unsigned int)depth_config->current_on_threshold, (unsigned int)depth_config->current_off_threshold, \
(unsigned int)depth_config->move_on_duratino, (unsigned int)depth_config->move_off_duration, (unsigned int)depth_config->move_current_channel); (unsigned int)depth_config->move_on_duratino, (unsigned int)depth_config->move_off_duration, (unsigned int)depth_config->move_current_channel);
#endif
// fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
// if (depth_config->magic != MAGIC)
// {
// ESP_LOGW(TAG, "fram_read depth_config failed, use default value");
// memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg));
// }
} }
//恢复默认配置 //恢复默认配置
@ -110,10 +152,10 @@ void restore_default(void)
{ {
memcpy(cal_4_20ma, &default_cal_4_20ma, sizeof(default_cal_4_20ma)); memcpy(cal_4_20ma, &default_cal_4_20ma, sizeof(default_cal_4_20ma));
memcpy(flow_config, &default_flow_cfg, sizeof(default_flow_cfg)); memcpy(flow_config, &default_flow_cfg, sizeof(default_flow_cfg));
// memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg)); memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg));
fram_write(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma)); fram_write(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma));
fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg)); fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg));
// fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
} }
void save_cal_4_20ma(void) void save_cal_4_20ma(void)
@ -131,7 +173,6 @@ void save_flow_cfg(void)
flow_config->magic = fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg)); flow_config->magic = fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg));
} }
#if 1
void save_depth_cfg(void) void save_depth_cfg(void)
{ {
ESP_LOGW(TAG, "save_depth_cfg: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", \ ESP_LOGW(TAG, "save_depth_cfg: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", \
@ -143,19 +184,9 @@ void save_depth_cfg(void)
depth_config->magic = MAGIC; depth_config->magic = MAGIC;
depth_config->magic = fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); depth_config->magic = fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
} }
#endif
void save_pile_id(void) void save_pile_id(void)
{ {
uint16_t temp[2] = {MAGIC, last_pile_id}; uint16_t temp[2] = {MAGIC, *cur_pile_id};
fram_write(0, &temp, sizeof(temp)); fram_write(0, &temp, sizeof(temp));
} }
void config_init(void)
{
ESP_ERROR_CHECK(i2c_master_init());
restore_default();
save_cal_4_20ma();
save_flow_cfg();
config_load();//读取保存在FRAM里的数据
}

196
main/stm32/config.h Normal file
View File

@ -0,0 +1,196 @@
#ifndef SYS_H__
#define SYS_H__
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#define FLOW_REG_ADDR 0
#define DEPTH_REG_ADDR 12
#define AC_CURRENT_REG_ADDR 24
#define MOVE_REG_ADDR 27
#define TILT_SENSER_ADDR 30
#define RECORD_REG_ADDR 32
#define TIME 264
#define CAL_4_20MA_ADDR 384
#define FLOW_CONFIG_ADDR (CAL_4_20MA_ADDR + (sizeof(cal_4_20ma_t) + 15) / 16 * 8)
#define DEPTH_CONFIG_ADDR (FLOW_CONFIG_ADDR + (sizeof(flow_config_t) + 15) / 16 * 8)
#define AD_RAW_REG_ADDR 444
#define LAST_PILE_ID_ADDR 509
#define DEPTH_RESET_ADDR 510
#define REBOOT_REW_ADDR 511
#define REG_GPS_MESSAGE (512 + 48)
#define REG_GPS_WRITE_DATA (REG_GPS_MESSAGE + sizeof(gps_message_t))
// // GPS数据
// typedef struct gps_message
// {
// uint8_t gps_status; // GPS定位状态
// uint8_t gps_view; // GPS可视状态
// uint8_t gps_use; // GPS使用状态
// uint8_t reg[1]; // 保留
// uint32_t utc; // utc时间
// double x; // 大地平面坐标
// double y;
// double dir; // 方向
// double pitch; // 俯仰角
// } gps_message_t;
// extern gps_message_t *gpsMessageP;
#define WRITE_DOWN_MAGIC 0x55BB // 控制gps采用参数进行运算
#define WRITE_SAVE_MAGIC 0x55AA // 控制gps将参数保存成json文件开机的时候自动加载
typedef struct gps_write_data // addr 600
{
uint16_t magic; // 600 2
uint16_t ellipsoidal_datum; // 椭圆基准 601 2
uint8_t reg[4];
// 604 8
int16_t x0; // 卫星接收器点坐标(坐标系以基站为原点建立)
int16_t y0;
int16_t x1; // 待求点坐标
int16_t y1;
// 608 16
uint64_t central_meridian; // 中央子午线
uint64_t elevation; // 投影高程
// 616 16
int64_t dx; // x轴平移
int64_t ax; // x轴旋转
// 624 16
int64_t dy; // y轴平移
int64_t ay; // y轴旋转
// 632 16
int64_t dz; // z轴平移
int64_t az; // z轴旋转
// 640 8
int64_t k; // 缩放比例
} gps_write_data_t;
extern gps_write_data_t *gpsWriteDataP;
typedef struct
{
uint16_t magic;
struct _ch
{
uint16_t ad_4ma;
uint16_t ad_20ma;
} ch[2];
} cal_4_20ma_t;
typedef struct
{
int16_t flow_min;
int16_t flow_max;
} ad_flow_cal_t; //存储ad转换的最大流量和最小流量
typedef struct
{
uint16_t magic; //可能是一个用于标识流量配置的特殊字段或标志?
uint16_t input_type; // 1 : 4~20ma 2: 0~3.6K
int16_t min_flow[2]; // 小流量切除
ad_flow_cal_t ad_cal[2];
uint16_t pulse_coef[2]; //可能代表了脉冲输出的系数或倍率?
uint16_t rsv[6]; //可能是预留给未来扩展使用的保留字段?
} flow_config_t;
typedef struct
{
uint16_t magic;
uint8_t input_type; // 0正交 1:正交反向 2:方向脉冲 3:方向脉冲反向
uint8_t port; // 编码器端口
uint16_t N; //编码器系数分子
uint16_t M; //编码器系数分母
// int pluse_coef; // 脉冲系数0.001mm
int16_t min_depth; // 最小深度 mm
int16_t max_depth; // 最大深度 mm
int16_t sample_depth; // 采样深度 mm
int16_t depth_offset; // 默认深度偏移
int16_t min_valid_depth; // 最小有效深度
int16_t inc_pile_depth; // 允许换桩深度
uint16_t current_on_threshold; // 行走电机开启电流
uint16_t current_off_threshold; // 行走电机关闭电流
uint16_t move_on_duratino; // 持续时间
uint16_t move_off_duration; // 持续时间
uint16_t move_current_channel; //行走电流通道
} depth_config_t;
typedef struct
{
int16_t flow_;
int16_t flow;
int32_t total_flow;
uint32_t update_time;
} flow_t;
typedef struct
{
uint16_t status; // 0:未开始 1:开始 2:结束
uint16_t time_count; // 持续时间 单位100ms
uint16_t work_time; // 行走的时间
uint16_t work_stop_state_flag;
uint16_t pile_inc_req;
} move_t;
typedef struct
{
uint16_t pile_work_state_and_direction; // 12
int16_t speed; // 13
int16_t depth; // 14
uint16_t sample_count; // 15
uint16_t depth_flow[2]; // 16~17
uint32_t last_total_flow[2]; //
int16_t depth_offset; // 22
uint16_t one_pile_work_time;//23 系统工作时间
// uint32_t update_time;
// int16_t tilt_x;
// int16_t tilt_y;
// uint16_t current1;
// uint16_t current2;
// uint16_t current3;
} depth_t;
typedef struct
{
int16_t max_depth;
uint16_t pile_id;
uint16_t count;
// uint16_t work_time;
struct _item
{
int16_t speed;
int16_t depth;
int16_t flow[2];
uint32_t total_flow[2];
int16_t tilt_x;
int16_t tilt_y;
uint16_t current1;
uint16_t current2;
} item[10];
} record_t;
extern depth_config_t *depth_config;
void config_load(void);
void save_cal_4_20ma(void);
void save_flow_cfg(void);
void save_depth_cfg(void);
void restore_default(void);
void save_pile_id(void);
#endif

1019
main/stm32/depth.c Normal file

File diff suppressed because it is too large Load Diff

14
main/stm32/depth.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __DEPTH_H
#define __DEPTH_H
#include "config.h"
#define PILE_STATE_STOP 0x0100
#define PILE_STATE_PAUSE 0x0200
#define PILE_STATE_WORK 0x0300
extern depth_t *depth_data;
void zero_depth(void);
#endif

334
main/stm32/flow.c Normal file
View File

@ -0,0 +1,334 @@
#include "stdlib.h"
#include "utils.h"
#include "config.h"
#include "ads1220.h"
#include "fram.h"
#include "modbuss.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "driver/mcpwm.h"
int zero_totalflow_req = 0;
const static char *TAG = "flow";
typedef struct capture_event
{
int ch;
uint32_t val;
} capture_event_t;
#define FLOW1_PIN_ECHO GPIO_NUM_39 // 捕获GPIO端口
#define FLOW2_PIN_ECHO GPIO_NUM_38 // 捕获GPIO端口
#define TRIGGER_THREAD_PRIORITY 5
extern int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time);
typedef struct
{
uint32_t capture_signal;
mcpwm_capture_signal_t sel_cap_signal;
} capture;
// static uint32_t cap_val_begin_of_flow1 = 0;
// static uint32_t cap_val_end_of_flow1 = 0;
// static uint32_t cap_val_begin_of_flow2 = 0;
// static uint32_t cap_val_end_of_flow2 = 0;
//static xQueueHandle cap_queue;
extern uint32_t rtc_clk_apb_freq;
uint32_t volatile t15_ccr[2];
uint16_t volatile t15_ccr_times[2];
cal_4_20ma_t *cal_4_20ma = (cal_4_20ma_t *)&gWordVar[CAL_4_20MA_ADDR];
flow_config_t *flow_config = (flow_config_t *)&gWordVar[FLOW_CONFIG_ADDR];
flow_t *pflow = (flow_t *)&gWordVar[FLOW_REG_ADDR];
void capture_flow1_init();
void capture_flow2_init();
extern void ADS1220_Init(void);
uint32_t volatile last_ccr[2] = {0};
extern int ad_value[4];
extern int ad_update_time[4];
extern uint8_t ad_watchdog_cnt;
extern int ad_values[4];
extern int ad_update_time[4];
uint32_t flow_update_time[2];
uint8_t timeout[2] = {0};
int flow_rem[2] = {0};
static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
t15_ccr[0] = edata->cap_value;
t15_ccr_times[0]++;
return high_task_wakeup == pdFALSE;
}
void capture_flow1_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pulldown_en(FLOW1_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf));
ESP_LOGI(TAG, "capture_flow_init");
}
static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata,
void *arg)
{
// calculate the interval in the ISR,
// so that the interval will be always correct even when cap_queue is not handled in time and overflow.
BaseType_t high_task_wakeup = pdFALSE;
t15_ccr[1] = edata->cap_value;
// t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
t15_ccr_times[1]++;
// send measurement back though queue
// xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup);
return high_task_wakeup == pdFALSE;
}
void capture_flow2_init()
{
ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO));
// enable pull down CAP0, to reduce noise
ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO));
// enable both edge capture on CAP0
mcpwm_capture_config_t conf = {
.cap_edge = MCPWM_NEG_EDGE,
.cap_prescale = 1,
.capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数
.user_data = NULL};
ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf));
ESP_LOGI(TAG, "capture_flow_init");
}
// void capture_task(void)
// {
// while (true) {
// capture_event_t cap_event = {.val = 0, .ch = 1};
// uint32_t pulse_width_us = 0;
// // block and wait for new measurement
// // ESP_LOGI(TAG, "xQueueReceive started");
// xQueueReceive(cap_queue, &cap_event, portMAX_DELAY);
// // ESP_LOGI(TAG, "xQueueReceive after");
// // ESP_LOGI(TAG, " cap_event.val: %d, cap_event.ch : %d", cap_event.val, cap_event.ch);
// switch (cap_event.ch)
// {
// case 1: //flow1 capture
// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
// ESP_LOGI(TAG, " (flow1 capture) Pulse width: %uus", pulse_width_us);
// break;
// case 2: //flow2 capture
// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq);
// ESP_LOGI(TAG, "(flow2 capture) Pulse width: %uus", pulse_width_us);
// break;
// default: ESP_LOGI(TAG, " default\n");
// break;
// }
// }
// }
void flow_init(void)
{
// // 流量 初始化捕获定时器
// // capture_flow2_init();
// // MX_TIM15_Init();
// // HAL_TIM_Base_Start_IT(&htim15);
// if (flow_config->input_type == 1)
// { // 4~20ma
// // ADS1220_Init();
// }
// else if (flow_config->input_type == 2)
// { // freq
// // HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_1);
// // HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_2);
// capture_flow1_init();
// capture_flow2_init();
// }
capture_flow1_init();
capture_flow2_init();
}
extern void zero_totalflow(int ch);
void flow_task(void *arg)
{
static uint32_t cp_flow_tick = 0;
static uint32_t ad_flow_tick = 100;
//int lock_time_out = 0;
while (1)
{
vTaskDelay(pdMS_TO_TICKS(100));
if (flow_config->input_type == 2 && TickDiff(cp_flow_tick) > 100)
{
int ch;
cp_flow_tick = xTaskGetTickCount();
for (ch = 0; ch < 2; ch++)
{
if (t15_ccr_times[ch] > 0)
{
int ccr_times;
int time_diff;
uint32_t ccr;
// __disable_irq();
ccr_times = t15_ccr_times[ch];
t15_ccr_times[ch] = 0;
ccr = t15_ccr[ch];
ccr = ccr / (rtc_clk_apb_freq / 1000000);
// __enable_irq();
time_diff = ccr - last_ccr[ch];
ESP_LOGI(TAG, "(type2) t15_ccr_times[%d]: %lu %d time_diff: %d", ch, ccr, ccr_times, time_diff);
ESP_LOGI(TAG,"rtc_clk_apb_freq : %lu\n", rtc_clk_apb_freq);
if (time_diff != 0)
{
int t_flow;
pflow[ch].flow_ = flow_config->pulse_coef[ch] * 600 * (int64_t)ccr_times / time_diff;
if (pflow[ch].flow_ < flow_config->min_flow[ch])
{
pflow[ch].flow = 0;
}
else
{
pflow[ch].flow = pflow[ch].flow_;
}
t_flow = pflow[ch].flow * time_diff / (5 * 60);
flow_rem[ch] += t_flow;
pflow[ch].total_flow += flow_rem[ch] / 10000;
flow_rem[ch] = flow_rem[ch] % 10000;
pflow[ch].update_time = ccr;
last_ccr[ch] = ccr;
timeout[ch] = 0;
// ESP_LOGI(TAG, "(type2) pflow[%d].flow: %u", ch ,pflow[ch].flow);
}
}
if (++timeout[ch] > 5)
{
timeout[ch] = 0;
pflow[ch].flow = 0;
pflow[ch].flow_ = 0;
}
}
}
// if (flow_config->input_type == 1 && TickDiff(ad_flow_tick) > 200)
// {
// int i;
// ad_flow_cal_t *cal = flow_config->ad_cal;
// ad_flow_tick = xTaskGetTickCount();
// for (i = 0; i < 2; i++)
// {
// int ad_ch = i * 2 + 1;
// int time_diff = abs_sub(ad_update_time[ad_ch], pflow[i].update_time);
// if (time_diff != 0)
// {
// int t_flow; // time_diff时间段总流量
// pflow[i].flow_ = scale(ad_value[ad_ch], cal_4_20ma->ch[i].ad_4ma, cal_4_20ma->ch[i].ad_20ma, cal[i].flow_min, cal[i].flow_max);
// if (pflow[i].flow_ < flow_config->min_flow[i])
// {
// pflow[i].flow = 0;
// }
// else
// {
// pflow[i].flow = pflow[i].flow_;
// }
// // 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为20uS
// // flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s
// // t_diff = time_diff / 50000 将时间差换算成秒
// // t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL
// // 取出0.01L的整数部分累加,余数部分和下次值累加
// // t_flow = pflow[i].flow * 1000 * time_diff / 500000 / 60;
// int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000);
// t_flow = pflow[i].flow * time_diff_us / 60 / 100;
// flow_rem[i] += t_flow;
// pflow[i].total_flow += flow_rem[i] / 10000;
// flow_rem[i] = flow_rem[i] % 10000;
// pflow[i].update_time = ad_update_time[ad_ch];
// timeout[i] = 0;
// ESP_LOGI(TAG, "(type1) flow_rem[%d].flow: %u", i, pflow[i].flow);
// }
// if (++timeout[i] > 10)
// {
// timeout[i] = 0;
// pflow[i].flow = 0;
// pflow[i].flow_ = 0;
// }
// }
// }
// if(zero_totalflow_req){
// zero_totalflow_req = 0;
// zero_totalflow(0);
// zero_totalflow(1);
// }
}
}
// 获取给定时刻累计流量
int get_total_flow_by_time(int ch, uint32_t time)
{
int delta_t;
int delta_flow;
if (ch > 1)
{
return 0;
}
delta_t = abs_sub(time, pflow[ch].update_time) / (APB_CLK_FREQ / 1000000); // 换算成us
delta_flow = pflow[ch].flow * delta_t / 60 / 100;
return pflow[ch].total_flow + delta_flow;
}
void zero_totalflow(int ch)
{
if (ch > 1)
{
return;
}
pflow[ch].total_flow = 0;
flow_rem[ch] = 0;
}
void zero_flow2(void)
{
memset(pflow, 0, sizeof(flow_t) * 2);
// ESP_LOGI(TAG, "%d %d", (int)pflow[0].total_flow, (int)pflow[1].total_flow);
for (int i = 0; i < 2; i++)
{
last_ccr[i] = 0;
flow_rem[i] = 0;
timeout[i] = 0;
t15_ccr[i] = 0;
t15_ccr_times[i] = 0;
}
}
void FLOW_init()
{
flow_init();
xTaskCreate(flow_task, "flow_task", 4096, NULL, 10, NULL);
}

7
main/stm32/flow.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef __FLOW_H
#define __FLOW_H
void zero_flow2(void);
#endif

View File

@ -1,14 +1,55 @@
#include "fram.h"
#include "string.h"
#include <stdio.h> #include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h" #include "driver/i2c.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h" #include "esp_system.h"
#include "sdkconfig.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_log.h"
#include "fram.h" static const char *TAG = "i2c-simple-example";
static const char *TAG = "fram"; #define I2C_MASTER_SCL_IO 1 /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO 2 /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define MPU9250_SENSOR_ADDR 0x68 /*!< Slave address of the MPU9250 sensor */
#define MPU9250_WHO_AM_I_REG_ADDR 0x75 /*!< Register addresses of the "who am I" register */
#define MPU9250_PWR_MGMT_1_REG_ADDR 0x6B /*!< Register addresses of the power managment register */
#define MPU9250_RESET_BIT 7
#define WRITE_BIT I2C_MASTER_WRITE
#define ACK_CHECK_EN 0x1
#define TAG "FREM"
/**
* @brief Read a sequence of bytes from a MPU9250 sensor registers
*/
// static esp_err_t mpu9250_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
// {
// return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
// }
/**
* @brief Write a byte to a MPU9250 sensor register
*/
// static esp_err_t mpu9250_register_write_byte(uint8_t reg_addr, uint8_t data)
// {
// int ret;
// uint8_t write_buf[2] = {reg_addr, data};
// ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
// return ret;
// }
/** /**
* @brief i2c master initialization * @brief i2c master initialization
@ -31,7 +72,7 @@ esp_err_t i2c_master_init(void)
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
} }
int fram_write(uint16_t addr, void *buf,uint32_t len) int fram_write(uint16_t addr, void * buf,uint32_t len)
{ {
esp_err_t ret; esp_err_t ret;
uint8_t slave_addr = (0xA0) | ((addr >> 8) & 0x7);/*page select*/ uint8_t slave_addr = (0xA0) | ((addr >> 8) & 0x7);/*page select*/
@ -55,7 +96,6 @@ int fram_write(uint16_t addr, void *buf,uint32_t len)
i2c_cmd_link_delete(cmd); i2c_cmd_link_delete(cmd);
return ret; return ret;
} }
int fram_read(uint16_t addr,void * buf,uint32_t len) int fram_read(uint16_t addr,void * buf,uint32_t len)
{ {
// esp_err_t err = i2c_param_config(i2c_master_port, &conf); // esp_err_t err = i2c_param_config(i2c_master_port, &conf);
@ -78,12 +118,10 @@ void save_para(void)
{ {
} }
void save_encode(void) void save_encode(void)
{ {
} }
void read_para() void read_para()
{ {

31
main/stm32/fram.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef FRAM_H__
#define FRAM_H__
// #include "main.h"
// #include "i2c.h"
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_err.h"
int fram_write(uint16_t addr, void * buf,uint32_t len);
int fram_read(uint16_t addr,void * buf,uint32_t len);
//extern void fram_write_para(fram_para_t *para,uint32_t len);
//extern void fram_read_para(fram_para_t *para,uint32_t len);
void save_para(void);
void save_encode(void);
void read_para(void);
void clear_para(void);
#endif

296
main/stm32/master.c Normal file
View File

@ -0,0 +1,296 @@
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "string.h"
#include "esp_log.h"
#include "modbus_params.h" // for modbus parameters structures
#include "mbcontroller.h"
#include "sdkconfig.h"
#define MB_PORT_NUM (CONFIG_MB_UART_PORT_NUM) // Number of UART port used for Modbus connection
#define MB_DEV_SPEED (CONFIG_MB_UART_BAUD_RATE) // The communication speed of the UART
// Note: Some pins on target chip cannot be assigned for UART communication.
// See UART documentation for selected board and target to configure pins using Kconfig.
// The number of parameters that intended to be used in the particular control process
#define MASTER_MAX_CIDS num_device_parameters
// Number of reading of parameters from slave
#define MASTER_MAX_RETRY 30
// Timeout to update cid over Modbus
#define UPDATE_CIDS_TIMEOUT_MS (500)
#define UPDATE_CIDS_TIMEOUT_TICS (UPDATE_CIDS_TIMEOUT_MS / portTICK_RATE_MS)
// Timeout between polls
#define POLL_TIMEOUT_MS (1)
#define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_RATE_MS)
// The macro to get offset for parameter in the appropriate structure
#define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1))
#define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
#define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1))
// Discrete offset macro
#define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1))
#define STR(fieldname) ((const char*)( fieldname ))
// Options can be used as bit masks or parameter limits
#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
static const char *TAG = "MASTER_TEST";
// Enumeration of modbus device addresses accessed by master device
enum {
MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here)
};
// Enumeration of all supported CIDs for device (used in parameter definition table)
enum {
CID_INP_DATA_0 = 0,
CID_HOLD_DATA_0,
CID_INP_DATA_1,
CID_HOLD_DATA_1,
CID_INP_DATA_2,
CID_HOLD_DATA_2,
CID_HOLD_TEST_REG,
CID_RELAY_P1,
CID_RELAY_P2,
CID_COUNT
};
// Example Data (Object) Dictionary for Modbus parameters:
// The CID field in the table must be unique.
// Modbus Slave Addr field defines slave address of the device with correspond parameter.
// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such).
// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly.
// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value.
// Data Type, Data Size specify type of the characteristic and its data size.
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_INP_DATA_0, STR("Data_channel_0"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2,
INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT, 4, OPTS( -10, 10, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_DATA_0, STR("Humidity_1"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2,
HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2,
INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2,
HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2,
INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2,
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 10, 58,
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8,
COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_RELAY_P2, STR("RelayP2"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 8, 8,
COIL_OFFSET(coils_port1), PARAM_TYPE_U16, 2, OPTS( BIT0, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER }
};
// Calculate number of parameters in the table
const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0]));
// The function to get pointer to parameter storage (instance) according to parameter description table
static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor)
{
assert(param_descriptor != NULL);
void* instance_ptr = NULL;
if (param_descriptor->param_offset != 0) {
switch(param_descriptor->mb_param_type)
{
case MB_PARAM_HOLDING:
instance_ptr = ((void*)&holding_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_INPUT:
instance_ptr = ((void*)&input_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_COIL:
instance_ptr = ((void*)&coil_reg_params + param_descriptor->param_offset - 1);
break;
case MB_PARAM_DISCRETE:
instance_ptr = ((void*)&discrete_reg_params + param_descriptor->param_offset - 1);
break;
default:
instance_ptr = NULL;
break;
}
} else {
ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid);
assert(instance_ptr != NULL);
}
return instance_ptr;
}
// User operation function to read slave values and check alarm
static void master_operation_func(void *arg)
{
esp_err_t err = ESP_OK;
float value = 0;
bool alarm_state = false;
const mb_parameter_descriptor_t* param_descriptor = NULL;
ESP_LOGI(TAG, "Start modbus test...");
for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) {
// Read all found characteristics from slave(s)
for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++)
{
// Get data from parameters description table
// and use this information to fill the characteristics description table
// and having all required fields in just one table
err = mbc_master_get_cid_info(cid, &param_descriptor);
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
void* temp_data_ptr = master_get_param_data(param_descriptor);
assert(temp_data_ptr);
uint8_t type = 0;
if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
(param_descriptor->cid == CID_HOLD_TEST_REG)) {
// Check for long array of registers of type PARAM_TYPE_ASCII
err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
(uint8_t*)temp_data_ptr, &type);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
*(uint32_t*)temp_data_ptr);
// Initialize data of test array and write to slave
if (*(uint32_t*)temp_data_ptr != 0xAAAAAAAA) {
memset((void*)temp_data_ptr, 0xAA, param_descriptor->param_size);
*(uint32_t*)temp_data_ptr = 0xAAAAAAAA;
err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key,
(uint8_t*)temp_data_ptr, &type);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
*(uint32_t*)temp_data_ptr);
} else {
ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(int)err,
(char*)esp_err_to_name(err));
}
}
} else {
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(int)err,
(char*)esp_err_to_name(err));
}
} else {
err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key,
(uint8_t*)&value, &type);
if (err == ESP_OK) {
*(float*)temp_data_ptr = value;
if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) ||
(param_descriptor->mb_param_type == MB_PARAM_INPUT)) {
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
value,
*(uint32_t*)temp_data_ptr);
if (((value > param_descriptor->param_opts.max) ||
(value < param_descriptor->param_opts.min))) {
alarm_state = true;
break;
}
} else {
uint16_t state = *(uint16_t*)temp_data_ptr;
const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF";
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(char*)param_descriptor->param_units,
(const char*)rw_str,
*(uint16_t*)temp_data_ptr);
if (state & param_descriptor->param_opts.opt1) {
alarm_state = true;
break;
}
}
} else {
ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
param_descriptor->cid,
(char*)param_descriptor->param_key,
(int)err,
(char*)esp_err_to_name(err));
}
}
vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls
}
}
vTaskDelay(UPDATE_CIDS_TIMEOUT_TICS); //
}
if (alarm_state) {
ESP_LOGI(TAG, "Alarm triggered by cid #%d.",
param_descriptor->cid);
} else {
ESP_LOGE(TAG, "Alarm is not triggered after %d retries.",
MASTER_MAX_RETRY);
}
ESP_LOGI(TAG, "Destroy master...");
ESP_ERROR_CHECK(mbc_master_destroy());
}
// Modbus master initialization
static esp_err_t master_init(void)
{
// Initialize and start Modbus controller
mb_communication_info_t comm = {
.port = MB_PORT_NUM,
#if CONFIG_MB_COMM_MODE_ASCII
.mode = MB_MODE_ASCII, //串口
#elif CONFIG_MB_COMM_MODE_RTU
.mode = MB_MODE_RTU, //RS485
#endif
.baudrate = MB_DEV_SPEED,
.parity = MB_PARITY_NONE
};
void* master_handler = NULL;
esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler);
MB_RETURN_ON_FALSE((master_handler != NULL), ESP_ERR_INVALID_STATE, TAG,
"mb controller initialization fail.");
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mb controller initialization fail, returns(0x%x).",
(uint32_t)err);
err = mbc_master_setup((void*)&comm);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mb controller setup fail, returns(0x%x).",
(uint32_t)err);
// Set UART pin numbers
err = uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD, CONFIG_MB_UART_RXD,
CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err);
err = mbc_master_start();
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
"mb controller start fail, returns(0x%x).",
(uint32_t)err);
// Set driver mode to Half Duplex
err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX);
MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,

100
main/stm32/pile_id.c Normal file
View File

@ -0,0 +1,100 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "pile_id.h"
#include "config.h"
#include "modbusS.h"
#include "flow.h"
#include "depth.h"
#include "../communication_pad/inc/communication_pad.h"
#include "ads1220.h"
#define TAG "pile_id"
uint16_t *cur_pile_id = &gWordVar[LAST_PILE_ID_ADDR];
gps_message_t *gps_message = (gps_message_t *)&gWordVar[REG_GPS_MESSAGE];
double gps_xy[2];
int none_flag = 1;
extern move_t *pMoveCtx;
extern int depth_over_inc_pile_flag;
static double double_abs(double a, double b)
{
if (a > b) return a - b;
else return b - a;
}
int gps_distance_check(void)
{
if (gps_message->gps_status != 4) // gps信号不是精准定位则不启用
{
none_flag = 1;
return 0;
}
if (none_flag) return 0;
if (double_abs(gps_message->x, gps_xy[0]) > GPS_DISTANCE_TH) return 1;
if (double_abs(gps_message->y, gps_xy[1]) > GPS_DISTANCE_TH) return 1;
return 0;
}
void inc_pile_fun(void)
{
ESP_LOGI(TAG, "inc pile");
// 增加桩号
(*cur_pile_id)++;
save_pile_id();
// 更新判断的标志数据
depth_over_inc_pile_flag = 0;
pMoveCtx->work_time = 0;
pMoveCtx->work_stop_state_flag = 0;
gps_xy[0] = gps_message->x;
gps_xy[1] = gps_message->y;
none_flag = 0;
// 清空数据
zero_flow1();
zero_flow2();
zero_depth();
}
// 轮询检查是否换桩
void pile_id_check_task(void)
{
static uint16_t last_pile_work_state = PILE_STATE_STOP;
while (1)
{
// 自动更新工作状态
if (last_pile_work_state == PILE_STATE_STOP) // 判断是否开始
{
if (gWordVar[AC_CURRENT_REG_ADDR + 0] > CURRENT0_TH && depth_over_inc_pile_flag == 1) // 钻头电流开 && 深度超过阈值
{
depth_data->pile_work_state_and_direction = (depth_data->pile_work_state_and_direction & 0XFF) | PILE_STATE_WORK;
}
}
if (last_pile_work_state == PILE_STATE_WORK) // 判断是否结束
{
if (pMoveCtx->work_stop_state_flag == 1 || gps_distance_check())
{
depth_data->pile_work_state_and_direction = (depth_data->pile_work_state_and_direction & 0XFF) | PILE_STATE_STOP;
}
}
// 开始则换桩
if ((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_WORK && last_pile_work_state == PILE_STATE_STOP)
{
inc_pile_fun();
}
last_pile_work_state = depth_data->pile_work_state_and_direction & 0xff00;
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void pile_id_init(void)
{
xTaskCreate(pile_id_check_task, "ads1220_task", 4096, NULL, 10, NULL);
}

10
main/stm32/pile_id.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __PILE_ID_H
#define __PILE_ID_H
#define CURRENT0_TH 1000
#define CURRENT2_TIMEOUT_TH 200 // 单位100ms
#define GPS_DISTANCE_TH (0.5)
void pile_id_init(void);
#endif

View File

@ -0,0 +1,143 @@
/* UART Echo Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "uart.h"
static const char *TAG = "UART0";
#define BAUD_RATE (460800)
#define UART_PORT_NUM (0)
#define BUF_SIZE (256)
#define UART_READ_TOUT (50 / portTICK_PERIOD_MS)
#define LED1_GPIO_PIN 9
uint8_t txbuf[BUF_SIZE];
uint8_t rxbuf[BUF_SIZE];
extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc);
extern uint16_t gWordVar[];
void LED1_Toggle(void)
{
static unsigned char flg = 1;
if (flg)
{
gpio_set_level(LED1_GPIO_PIN, 0);
flg = 0;
}
else
{
gpio_set_level(LED1_GPIO_PIN, 1);
flg = 1;
}
}
void uart0_init(void)
{
const int uart_num = UART_PORT_NUM;
uart_config_t uart_config = {
.baud_rate = BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
.source_clk = UART_SCLK_APB,
};
// Set UART log level
// esp_log_level_set(TAG, ESP_LOG_NONE);
ESP_LOGI(TAG, "Start RS485 application test and configure UART.");
// Install UART driver (we don't need an event queue here)
// In this example we don't even use a buffer for sending data.
ESP_ERROR_CHECK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE, 0, NULL, 0));
// Configure UART parameters
ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
ESP_LOGI(TAG, "UART set pins, mode and install driver.");
// Set UART pins as per KConfig settings
//ESP_ERROR_CHECK(uart_set_pin(uart_num, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));之前没解开注释
//ESP_ERROR_CHECK(uart_set_pin(uart_num, 11, 13, 12, -1));
// Set RS485 half duplex mode
ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX));
// Set read timeout of UART TOUT feature
ESP_ERROR_CHECK(uart_set_rx_timeout(uart_num, UART_READ_TOUT));
}
void uart0_modbus_slave_task(void *arg)
{
uart0_init();
while (1)
{
int txlen = 0;
// for (int i = 0; i < 70; i++)
// txbuf[i] = i;
// int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, 70);
// ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length);
// for (int i = 0; i < uart_write_length; i++)
// ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]);
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// vTaskDelay(1000 / portTICK_PERIOD_MS);
// continue;
// ESP_LOGI("modbus_slave","---------");
int len = uart_read_bytes(UART_PORT_NUM, rxbuf, BUF_SIZE, UART_READ_TOUT);
/*uint32_t tick = */xTaskGetTickCount();
// ESP_LOGI("modbus_slave","-----------------------------rxlen:%d", len);
// for (int i = 0; i < len; i++)
// ESP_LOGI("modbus_slave","uart0 get: 0x%x", rxbuf[i]);
if (len > 0)
{
txlen = ModbusSlaveProcess(txbuf, rxbuf, len, 1);
if (txlen > 0)
{
LED1_Toggle();
int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, txlen);
// ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length);
// for (int i = 0; i < uart_write_length; i++)
// ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]);
}
}
// if (tick - last_rxtick >= PACKET_READ_TICS)
// {
// com_poll_modbus_master_poll(0);
// // if (++mcu_watch_dog_cnt > mcu_watch_dog_timeout) //如果通讯中断会相互重启,计数器不起作用
// if (gpio_get_level(0)) // cpu 启动后会拉低GPIO0
// {
// mcu_watch_dog_cnt = 0;
// if (mcu_pwr_off_cnt < 2)
// {
// mcu_pwr_off_cnt++;
// gpio_set_level(12, 1); // 3v8 off
// vTaskDelay(3000 / portTICK_RATE_MS);
// gpio_set_level(12, 0); // 3v8 off
// mcu_watch_dog_timeout = 12000 / (portTICK_RATE_MS * PACKET_READ_TICS);
// }
// }
// }
// last_rxtick = tick;
}
}
void uart0_modbus_slave_init(void)
{
xTaskCreate(uart0_modbus_slave_task, "uart0_modbus_slave_task", 4096, NULL, 10, NULL);
}

View File

@ -0,0 +1,112 @@
/* UART Echo Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "uart.h"
/**
* This is an example which echos any data it receives on configured UART back to the sender,
* with hardware flow control turned off. It does not use UART driver event queue.
*
* - Port: configured UART
* - Receive (Rx) buffer: on
* - Transmit (Tx) buffer: off
* - Flow control: off
* - Event queue: off
* - Pin assignment: see defines below (See Kconfig)
*/
#define UART_TXD_PIN 11
#define UART_RXD_PIN 13
#define UART_RTS_PIN 12
#define UART_CTS_PIN (-1)
static const char *TAG = "UART1";
#define BAUD_RATE (9600)
#define UART_PORT_NUM (1)
#define RX_BUF_SIZE (256)
#define TX_BUF_SIZE (256)
#define UART_READ_TOUT (5 / portTICK_PERIOD_MS)
static void uart1_rs485_init(void)
{
uart_config_t uart_config = {
.baud_rate = BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
.source_clk = UART_SCLK_APB,
};
ESP_LOGI(TAG, "Start RS485 application test and configure UART.");
// Install UART driver (we don't need an event queue here)
// In this example we don't even use a buffer for sending data.
ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, RX_BUF_SIZE, TX_BUF_SIZE, 0, NULL, 0));
// Configure UART parameters
ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));
ESP_LOGI(TAG, "UART set pins, mode and install driver.");
// Set UART pins as per KConfig settings
ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));
// Set RS485 half duplex mode
ESP_ERROR_CHECK(uart_set_mode(UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
// Set read timeout of UART TOUT feature
ESP_ERROR_CHECK(uart_set_rx_timeout(UART_PORT_NUM, UART_READ_TOUT));
}
static void uart0_com_poll_task(void *arg)
{
uint32_t last_rxtick = 0;
uint8_t rx_data[RX_BUF_SIZE];
uint8_t tx_data[RX_BUF_SIZE];
while (1)
{
// Read data from UART
int len = uart_read_bytes(UART_PORT_NUM, rx_data, RX_BUF_SIZE, UART_READ_TOUT);
uint32_t tick = xTaskGetTickCount();
// Write data back to UART
if (len > 0)
{
// ESP_LOGI(TAG, "uart_read_bytes len=%d", len);
int err = com_poll_modbus_master_on_revice(0, data, len);
if (err == 0)
{
}
}
if (tick - last_rxtick >= UART_READ_TOUT)
{
com_poll_modbus_master_poll(0);
// if (++mcu_watch_dog_cnt > mcu_watch_dog_timeout) //如果通讯中断会相互重启,计数器不起作用
}
}
vTaskDelete(NULL);
}
void uart1_task_init(void)
{
ESP_LOGI(TAG, "uart1_com_poll_task");
// A uart read/write example without event queue;
xTaskCreate(uart0_com_poll_task, "uart0_com_poll_task", 1024, NULL, 9, NULL);
}

View File

@ -0,0 +1,61 @@
/* UART Echo Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "uart.h"
/**
* This is an example which echos any data it receives on configured UART back to the sender,
* with hardware flow control turned off. It does not use UART driver event queue.
*
* - Port: configured UART
* - Receive (Rx) buffer: on
* - Transmit (Tx) buffer: off
* - Flow control: off
* - Event queue: off
* - Pin assignment: see defines below (See Kconfig)
*/
#define UART_TXD_PIN 14
#define UART_RXD_PIN 21
#define UART_RTS_PIN (-1)
#define UART_CTS_PIN 47
static const char *TAG = "UART2";
#define UART2_BAUD_RATE (115200)
#define UART_PORT_NUM (2)
#define BUF_SIZE (1024)
static void uart2_init(void)
{
uart_config_t uart_config = {
.baud_rate = UART2_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));
}

View File

@ -2,11 +2,8 @@
#ifndef _UTILS_H_ #ifndef _UTILS_H_
#define _UTILS_H_ #define _UTILS_H_
#include <stdint.h>
int GetCompileDateTime(uint16_t *DateTime); int GetCompileDateTime(uint16_t *DateTime);
uint32_t TickDiff(uint32_t comptime); uint32_t TickDiff(uint32_t comptime);
int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max);
int abs_sub_uint32(uint32_t a, uint32_t b); int abs_sub_uint32(uint32_t a, uint32_t b);
#endif #endif

28
main/uart.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _UART_H_
#define _UART_H_
#define RS485_TXD_PIN 17
#define RS485_RXD_PIN 18
#define RS485_RTS_PIN 8
#define RS485_CTS_PIN (-1)
// #define MCU_TXD_PIN 17
// #define MCU_RXD_PIN 18
#define PRINT_TXD_PIN 16
#define PRINT_RXD_PIN 15
#define PRINT_RTS_PIN (-1)
#define PRINT_CTS_PIN 3
#define RS485_UART_PORT_NUM (0)
#define RS485_UART_BAUD_RATE (115200)
#define RS485_TASK_STACK_SIZE (1024)
#define PRINT_UART_PORT_NUM (1)
#define PRINT_UART_BAUD_RATE (115200)
#define PRINT_TASK_STACK_SIZE (1024)
#endif

97
main/uart_example.c Normal file
View File

@ -0,0 +1,97 @@
/* UART Echo Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "uart.h"
/**
* This is an example which echos any data it receives on configured UART back to the sender,
* with hardware flow control turned off. It does not use UART driver event queue.
*
* - Port: configured UART
* - Receive (Rx) buffer: on
* - Transmit (Tx) buffer: off
* - Flow control: off
* - Event queue: off
* - Pin assignment: see defines below (See Kconfig)
*/
#define RS485_TXD_PIN 17
#define RS485_RXD_PIN 18
#define RS485_RTS_PIN 8
#define RS485_CTS_PIN (-1)
// #define MCU_TXD_PIN 17
// #define MCU_RXD_PIN 18
#define PRINT_TXD_PIN 16
#define PRINT_RXD_PIN 15
#define PRINT_RTS_PIN (-1)
#define PRINT_CTS_PIN 3
#define RS485_UART_PORT_NUM (0)
#define RS485_UART_BAUD_RATE (115200)
#define RS485_TASK_STACK_SIZE (1024)
#define PRINT_UART_PORT_NUM (1)
#define PRINT_UART_BAUD_RATE (115200)
#define PRINT_TASK_STACK_SIZE (1024)
// static const char *TAG = "UART";
#define BUF_SIZE (1024)
void RS485_init(void)
{
uart_config_t uart_config = {
.baud_rate = RS485_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(RS485_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(RS485_UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(RS485_UART_PORT_NUM, RS485_TXD_PIN, RS485_RXD_PIN, RS485_RTS_PIN, RS485_CTS_PIN));
}
void print_init(void)
{
uart_config_t uart_config = {
.baud_rate = PRINT_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(PRINT_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(PRINT_UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(PRINT_UART_PORT_NUM, PRINT_TXD_PIN, PRINT_RXD_PIN, PRINT_RTS_PIN, PRINT_CTS_PIN));
}