Compare commits
2 Commits
8352283480
...
8f5dc1cadd
Author | SHA1 | Date | |
---|---|---|---|
|
8f5dc1cadd | ||
|
e90bd57a59 |
@ -1,26 +1,32 @@
|
||||
set(SRCS
|
||||
"uart_example.c"
|
||||
"main.c"
|
||||
"utils.c"
|
||||
"./modbus/ModbusS.c"
|
||||
"./modbus/uart0_modbus_slave.c"
|
||||
"./peripheral/led.c"
|
||||
"./peripheral/config/fram.c"
|
||||
"./peripheral/config/config.c"
|
||||
"./peripheral/flow/ads1220.c"
|
||||
"./peripheral/flow/input_type2.c"
|
||||
"./peripheral/flow/flow.c"
|
||||
"./peripheral/bl0939.c"
|
||||
"./peripheral/depth.c"
|
||||
"./peripheral/depth_.c"
|
||||
"modbus-tcp.c"
|
||||
"can_network.c"
|
||||
"./stm32/ads1220.c"
|
||||
"./stm32/bl0939.c"
|
||||
"./stm32/capture.c"
|
||||
"./stm32/comm.c"
|
||||
"./stm32/depth.c"
|
||||
"./stm32/fram.c"
|
||||
"./stm32/flow.c"
|
||||
"./stm32/utils.c"
|
||||
"./stm32/config.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
|
||||
"." "./inc"
|
||||
"./modbus/inc"
|
||||
"./peripheral/inc"
|
||||
"./peripheral/flow/inc"
|
||||
"./peripheral/config/inc"
|
||||
)
|
||||
set(INCLUDE_DIRS "." "./communication_pad/inc")
|
||||
|
||||
idf_component_register(SRCS ${SRCS}
|
||||
INCLUDE_DIRS ${INCLUDE_DIRS})
|
257
main/can_network.c
Normal file
257
main/can_network.c
Normal 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
19
main/can_network.h
Normal 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****/
|
687
main/communication_pad/ble_gatts_server.c
Normal file
687
main/communication_pad/ble_gatts_server.c
Normal 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);
|
||||
}
|
||||
}
|
170
main/communication_pad/communication_pad.c
Normal file
170
main/communication_pad/communication_pad.c
Normal 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
|
||||
* 如果是读寄存器功能,则从参数返回读取结果数组,否则返回NULL,注意,返回的指针需要手动free
|
||||
*/
|
||||
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!");
|
||||
}
|
32
main/communication_pad/inc/ble_gatts_server.h
Normal file
32
main/communication_pad/inc/ble_gatts_server.h
Normal 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
|
63
main/communication_pad/inc/communication_pad.h
Normal file
63
main/communication_pad/inc/communication_pad.h
Normal 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
|
23
main/communication_pad/inc/tcp_server.h
Normal file
23
main/communication_pad/inc/tcp_server.h
Normal 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
|
23
main/communication_pad/inc/udp_server.h
Normal file
23
main/communication_pad/inc/udp_server.h
Normal 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
|
6
main/communication_pad/inc/wifi_softap.h
Normal file
6
main/communication_pad/inc/wifi_softap.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __WIFI_SOFTAP_H
|
||||
#define __WIFI_SOFTAP_H
|
||||
|
||||
void wifi_init_softap(void);
|
||||
|
||||
#endif
|
170
main/communication_pad/tcp_server.c
Normal file
170
main/communication_pad/tcp_server.c
Normal 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;
|
||||
}
|
||||
}
|
169
main/communication_pad/udp_server.c
Normal file
169
main/communication_pad/udp_server.c
Normal 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;
|
||||
}
|
||||
}
|
99
main/communication_pad/wifi_softap.c
Normal file
99
main/communication_pad/wifi_softap.c
Normal 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);
|
||||
}
|
||||
|
154
main/main.c
154
main/main.c
@ -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/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.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 <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"
|
||||
#include "flow.h"
|
||||
#include "bl0939.h"
|
||||
#include "depth.h"
|
||||
|
||||
/* The examples use WiFi configuration that you can set via project configuration menu
|
||||
|
||||
If you'd rather not, just change the below entries to strings with
|
||||
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 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;
|
||||
|
||||
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)
|
||||
{
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
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();
|
||||
}
|
||||
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();
|
||||
flow_init();
|
||||
BL0939_init();
|
||||
// pcnt_rotary_encoder_init_();
|
||||
DEPTH_init();
|
||||
pad_communication_init();
|
||||
//ESP32_Uart_Receive_Data();
|
||||
|
||||
}
|
||||
|
||||
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
140
main/modbus-tcp.c
Normal 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
27
main/modbus-tcp.h
Normal 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****/
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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_));
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
680
main/stm32/ModbusM.c
Normal 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
120
main/stm32/ModbusM.h
Normal 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
|
@ -1,9 +1,13 @@
|
||||
#include <string.h>
|
||||
// #include "driver/ledc.h"
|
||||
// #include "esp_err.h"
|
||||
#include "esp_log.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";
|
||||
|
||||
@ -104,58 +108,70 @@ int isBitHI(uint16_t Add)
|
||||
void ModBusBitWriteHook(uint16_t addr, uint16_t length)
|
||||
{
|
||||
}
|
||||
|
||||
// extern void reset_depth(void);
|
||||
// uint16_t reboot_req ;
|
||||
extern void reset_depth(void);
|
||||
uint16_t reboot_req ;
|
||||
// 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)
|
||||
{
|
||||
// // ESP_LOGI(TAG, "ModBusWordWriteHook");
|
||||
// if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){
|
||||
// ESP_LOGI(TAG, "ModBusWordWriteHook");
|
||||
if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){
|
||||
// reset_depth();
|
||||
// gWordVar[RECORD_REG_ADDR] = 0;
|
||||
// }
|
||||
// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){
|
||||
// config_load();
|
||||
// gWordVar[DEPTH_RESET_ADDR] = 0;
|
||||
// }
|
||||
// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){
|
||||
// gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号
|
||||
gWordVar[RECORD_REG_ADDR] = 0;
|
||||
}
|
||||
if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){
|
||||
config_load();
|
||||
gWordVar[DEPTH_RESET_ADDR] = 0;
|
||||
}
|
||||
if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){
|
||||
gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号
|
||||
// reset_depth();
|
||||
// gWordVar[DEPTH_RESET_ADDR] = 0;
|
||||
// }
|
||||
// if(addr == LAST_PILE_ID_ADDR){
|
||||
// last_pile_id = gWordVar[LAST_PILE_ID_ADDR];
|
||||
// }
|
||||
// else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){
|
||||
gWordVar[DEPTH_RESET_ADDR] = 0;
|
||||
}
|
||||
if(addr == LAST_PILE_ID_ADDR){
|
||||
*cur_pile_id = gWordVar[LAST_PILE_ID_ADDR];
|
||||
}
|
||||
else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){
|
||||
save_flow_cfg();
|
||||
}
|
||||
else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){
|
||||
save_depth_cfg();
|
||||
}
|
||||
else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){
|
||||
save_cal_4_20ma();
|
||||
}
|
||||
// else if(addr >= FLOW_CONFIG_ADDR && addr < (FLOW_CONFIG_ADDR + sizeof(flow_config_t))/* && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa */){
|
||||
// save_flow_cfg();
|
||||
// }
|
||||
// else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){
|
||||
// else if(addr >= DEPTH_CONFIG_ADDR && addr < (DEPTH_CONFIG_ADDR + sizeof(depth_config_t))){
|
||||
// save_depth_cfg();
|
||||
// }
|
||||
// else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){
|
||||
// else if(addr >= CAL_4_20MA_ADDR && addr < (CAL_4_20MA_ADDR + sizeof(cal_4_20ma_t))){
|
||||
// save_cal_4_20ma();
|
||||
// }
|
||||
// else if(addr == REBOOT_REW_ADDR ){
|
||||
// if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){
|
||||
// reboot_req = 0x55aa;
|
||||
// }
|
||||
// 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);
|
||||
// }
|
||||
else if(addr == REBOOT_REW_ADDR ){
|
||||
if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){
|
||||
reboot_req = 0x55aa;
|
||||
}
|
||||
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)
|
||||
{
|
||||
// ESP_LOGI(TAG, "ModbusSlaveProcess");
|
||||
uint16_t crcData,crcChk;
|
||||
uint8_t Offset,ByteAdd;
|
||||
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校验*/
|
||||
if(is_crc != 0){
|
||||
@ -212,6 +228,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x04: //Read Holding Registers
|
||||
// ESP_LOGI(TAG, "read");
|
||||
if((add+length) > gWORD_SIZE)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case 0x06: //Write Single Register
|
||||
// ESP_LOGI(TAG, "write");
|
||||
// ESP_LOGI(TAG, "modbus 0x06");
|
||||
if(add >= gWORD_SIZE)
|
||||
{
|
||||
@ -279,7 +297,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr
|
||||
break;
|
||||
}
|
||||
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);
|
||||
memcpy(txbuf,rxbuf,6);
|
||||
ModBusWordWriteHook(add,1);
|
46
main/stm32/ModbusS.h
Normal file
46
main/stm32/ModbusS.h
Normal 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
426
main/stm32/ads1220.c
Normal 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
110
main/stm32/ads1220.h
Normal 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
|
@ -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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -5,16 +13,21 @@
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "bl0939.h"
|
||||
#include "depth.h"
|
||||
#include "gwordvar.h"
|
||||
#include "utils.h"
|
||||
#include "pile_id.h"
|
||||
|
||||
#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;
|
||||
move_t *pMoveCtx = (move_t *)&gWordVar[MOVE_REG_ADDR];
|
||||
|
||||
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 (++pMoveCtx->time_count > depth_config->move_on_duratino)
|
||||
if (++pMoveCtx->time_count > depth_config->move_on_duratino) // 时间单位和采样时间有关,100ms
|
||||
{
|
||||
pMoveCtx->status = 1;
|
||||
pMoveCtx->time_count = 0;
|
||||
pMoveCtx->work_time = 0;
|
||||
pMoveCtx->pile_inc_req = 1;
|
||||
pMoveCtx->work_stop_state_flag = 0;
|
||||
|
||||
// ESP_LOGI(TAG, "cur > th, status trun to on");
|
||||
}
|
||||
@ -254,18 +269,22 @@ void BL0939_task()
|
||||
else if (pMoveCtx->status == 1)
|
||||
{
|
||||
// ESP_LOGI(TAG, "mov status is on");
|
||||
pMoveCtx->work_time++;
|
||||
int move_current_channel = depth_config->move_current_channel;
|
||||
if (move_current_channel > 2 || move_current_channel < 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
pMoveCtx->status = 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");
|
||||
}
|
||||
}
|
31
main/stm32/bl0939.h
Normal file
31
main/stm32/bl0939.h
Normal 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
153
main/stm32/capture.c
Normal 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
104
main/stm32/comm.c
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "fram.h"
|
||||
#include "flow.h"
|
||||
#include "depth.h"
|
||||
#include "utils.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";
|
||||
|
||||
@ -53,8 +56,41 @@ const depth_config_t default_depth_cfg = {
|
||||
// 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};
|
||||
|
||||
#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 */
|
||||
/*
|
||||
通过 I2C 总线读取 ESP32 上连接的 FRAM(非易失性存储器)芯片中指定地址的数据
|
||||
@ -69,7 +105,7 @@ void config_load(void)
|
||||
{
|
||||
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));
|
||||
@ -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]);
|
||||
|
||||
#if 1
|
||||
fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
|
||||
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->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);
|
||||
#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(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_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)
|
||||
@ -131,7 +173,6 @@ void save_flow_cfg(void)
|
||||
flow_config->magic = fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg));
|
||||
}
|
||||
|
||||
#if 1
|
||||
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", \
|
||||
@ -143,19 +184,9 @@ void save_depth_cfg(void)
|
||||
depth_config->magic = MAGIC;
|
||||
depth_config->magic = fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg));
|
||||
}
|
||||
#endif
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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
196
main/stm32/config.h
Normal 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
1019
main/stm32/depth.c
Normal file
File diff suppressed because it is too large
Load Diff
14
main/stm32/depth.h
Normal file
14
main/stm32/depth.h
Normal 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
334
main/stm32/flow.c
Normal 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
7
main/stm32/flow.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __FLOW_H
|
||||
#define __FLOW_H
|
||||
|
||||
|
||||
void zero_flow2(void);
|
||||
|
||||
#endif
|
@ -1,14 +1,55 @@
|
||||
#include "fram.h"
|
||||
#include "string.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "sdkconfig.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, ®_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
|
||||
@ -55,7 +96,6 @@ int fram_write(uint16_t addr, void *buf,uint32_t len)
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fram_read(uint16_t addr,void * buf,uint32_t len)
|
||||
{
|
||||
// esp_err_t err = i2c_param_config(i2c_master_port, &conf);
|
||||
@ -78,12 +118,10 @@ void save_para(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void save_encode(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void read_para()
|
||||
{
|
||||
|
31
main/stm32/fram.h
Normal file
31
main/stm32/fram.h
Normal 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
296
main/stm32/master.c
Normal 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, ¶m_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
100
main/stm32/pile_id.c
Normal 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
10
main/stm32/pile_id.h
Normal 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
|
143
main/stm32/uart0_modbus_slave.c
Normal file
143
main/stm32/uart0_modbus_slave.c
Normal 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);
|
||||
}
|
112
main/stm32/uart1_modbus_master.c
Normal file
112
main/stm32/uart1_modbus_master.c
Normal 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);
|
||||
}
|
61
main/stm32/uart2_printer.c
Normal file
61
main/stm32/uart2_printer.c
Normal 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));
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,8 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int GetCompileDateTime(uint16_t *DateTime);
|
||||
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);
|
||||
|
||||
#endif
|
28
main/uart.h
Normal file
28
main/uart.h
Normal 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
97
main/uart_example.c
Normal 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));
|
||||
}
|
Loading…
Reference in New Issue
Block a user