新增86设置处理,TCA6416数字量输出OK

This commit is contained in:
qiuxin 2025-05-30 19:37:27 +08:00
parent f064a13b30
commit 44ac1747c0
6 changed files with 98 additions and 69 deletions

View File

@ -567,63 +567,19 @@ void test_tca6416_task(void const *argument)
tca6416_test_step = 1; tca6416_test_step = 1;
tca6416_init_result = TCA6416_Init(); tca6416_init_result = TCA6416_Init();
if(tca6416_init_result != 0)
{
// 初始化失败,停留在此步骤
tca6416_error_count++;
while(1)
{
osDelay(1000);
}
}
// 步骤2: 初始化第二个TCA6416芯片地址0x21 // 步骤2: 初始化第二个TCA6416芯片地址0x21
tca6416_test_step = 2; tca6416_test_step = 2;
tca6416_init2_result = TCA6416_Init2(); tca6416_init2_result = TCA6416_Init2();
if(tca6416_init2_result != 0)
{
tca6416_error_count++;
// 继续执行,不阻塞
}
// 步骤3: 初始化第三个TCA6416芯片地址0x20第二条总线 // 步骤3: 初始化第三个TCA6416芯片地址0x20第二条总线
tca6416_test_step = 3; tca6416_test_step = 3;
tca6416_init3_result = TCA6416_Init3(); tca6416_init3_result = TCA6416_Init3();
if(tca6416_init3_result != 0) // 设置第一个芯片Port0和Port1为输出0=输出1=输入)
{ // 注意输出状态由tcpecho_recv_control控制这里只设置方向
tca6416_error_count++;
// 继续执行,不阻塞
}
// 步骤4: 配置第一个芯片所有IO为输出模式并置高电平
tca6416_test_step = 4;
// 设置Port0和Port1为输出0=输出1=输入)
ret = TCA6416_SetPortDirection(0, 0x00); // Port0全部设为输出 ret = TCA6416_SetPortDirection(0, 0x00); // Port0全部设为输出
if(ret != 0)
{
tca6416_error_count++;
tca6416_i2c_ack_status = ret;
}
osDelay(10); osDelay(10);
ret = TCA6416_SetPortDirection(1, 0x00); // Port1全部设为输出 ret = TCA6416_SetPortDirection(1, 0x00); // Port1全部设为输出
if(ret != 0)
{
tca6416_error_count++;
tca6416_i2c_ack_status = ret;
}
osDelay(10);
// 将第一个芯片所有IO置为高电平
ret = TCA6416_WritePort(0, 0xFF);
if(ret == 0) tca6416_port0_status = 0xFF;
osDelay(10);
ret = TCA6416_WritePort(1, 0xFF);
if(ret == 0) tca6416_port1_status = 0xFF;
osDelay(10); osDelay(10);
// 步骤5: 配置第二、三个芯片所有IO为输入模式 // 步骤5: 配置第二、三个芯片所有IO为输入模式
@ -652,13 +608,7 @@ void test_tca6416_task(void const *argument)
for(;;) for(;;)
{ {
// 刷新第一个芯片的输出状态 // 读取第一个芯片状态由tcpecho_recv_control控制输出
TCA6416_WritePort(0, 0xFF);
osDelay(10);
TCA6416_WritePort(1, 0xFF);
osDelay(10);
// 读取第一个芯片状态
if(TCA6416_ReadPort(0, &tca6416_read_data) == 0) if(TCA6416_ReadPort(0, &tca6416_read_data) == 0)
{ {
tca6416_port0_status = tca6416_read_data; tca6416_port0_status = tca6416_read_data;

BIN
Public/~WRL3372.tmp Normal file

Binary file not shown.

View File

@ -5,18 +5,21 @@
#include <stdint.h> #include <stdint.h>
/* GPIO定义 */ /* GPIO定义 */
//第一条总线
#define TCA6416_SCL_PIN GPIO_PIN_2 #define TCA6416_SCL_PIN GPIO_PIN_2
#define TCA6416_SCL_PORT GPIOE #define TCA6416_SCL_PORT GPIOE
#define TCA6416_SDA_PIN GPIO_PIN_3 #define TCA6416_SDA_PIN GPIO_PIN_3
#define TCA6416_SDA_PORT GPIOE #define TCA6416_SDA_PORT GPIOE
//第二条总线
#define TCA6416_SCL_PIN2 GPIO_PIN_5 #define TCA6416_SCL_PIN2 GPIO_PIN_5
#define TCA6416_SCL_PORT2 GPIOE #define TCA6416_SCL_PORT2 GPIOE
#define TCA6416_SDA_PIN2 GPIO_PIN_4 #define TCA6416_SDA_PIN2 GPIO_PIN_4
#define TCA6416_SDA_PORT2 GPIOE #define TCA6416_SDA_PORT2 GPIOE
/* TCA6416 I2C地址 */ /* TCA6416 I2C地址 */
#define TCA6416_ADDR 0x20 // 第一个芯片地址 (A0=A1=A2=GND) #define TCA6416_ADDR 0x20 // 第一个芯片地址 (A0=A1=A2=GND)单独总线SDA PE3 SCL PE4
#define TCA6416_ADDR2 0x21 // 第二个芯片地址 (A0=1, A1=A2=GND) #define TCA6416_ADDR2 0x21 // 第二个芯片地址 (A0=1, A1=A2=GND)与TCA6416_ADDR3共用总线SDA PE4 SCL PE5
#define TCA6416_ADDR3 0x20 // 第三个芯片地址 (与第二个芯片共用总线地址0x20) #define TCA6416_ADDR3 0x20 // 第三个芯片地址 (与第二个芯片共用总线地址0x20)
@ -66,7 +69,7 @@
#define SDA_READ2() HAL_GPIO_ReadPin(TCA6416_SDA_PORT2, TCA6416_SDA_PIN2) #define SDA_READ2() HAL_GPIO_ReadPin(TCA6416_SDA_PORT2, TCA6416_SDA_PIN2)
/* 函数声明 */ /* 函数声明 */
void TCA6416_GPIO_Init(void);
uint8_t TCA6416_Init(void); uint8_t TCA6416_Init(void);
uint8_t TCA6416_Init2(void); // 第二个芯片的初始化函数 uint8_t TCA6416_Init2(void); // 第二个芯片的初始化函数
uint8_t TCA6416_Init3(void); // 第三个芯片的初始化函数 uint8_t TCA6416_Init3(void); // 第三个芯片的初始化函数
@ -100,5 +103,7 @@ uint8_t I2C_SendByte(uint8_t byte); // 修正返回值类型
void I2C_SendByte2(uint8_t byte); // 第二个芯片的发送字节 void I2C_SendByte2(uint8_t byte); // 第二个芯片的发送字节
uint8_t I2C_ReadByte(void); uint8_t I2C_ReadByte(void);
uint8_t I2C_ReadByte2(void); // 第二个芯片的读取字节 uint8_t I2C_ReadByte2(void); // 第二个芯片的读取字节
void TCA6416_GPIO_Init(void);
void TCA6416_GPIO_Init2(void); // 第二个芯片的I2C初始化
#endif /* __TCA6416_H */ #endif /* __TCA6416_H */

View File

@ -5,6 +5,7 @@
/** /**
* @brief TCA6416的GPIO * @brief TCA6416的GPIO
*/ */
//第一条IIC总线初始化
void TCA6416_GPIO_Init(void) void TCA6416_GPIO_Init(void)
{ {
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStruct = {0};
@ -12,20 +13,34 @@ void TCA6416_GPIO_Init(void)
// 使能GPIOE时钟 // 使能GPIOE时钟
__HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE();
// 配置第一个芯片的SCL和SDA引脚为开漏输出 //两个芯片挂一条总线上SDA PE3 SCL PE2
GPIO_InitStruct.Pin = TCA6416_SCL_PIN | TCA6416_SDA_PIN; GPIO_InitStruct.Pin = TCA6416_SCL_PIN | TCA6416_SDA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉 GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(TCA6416_SCL_PORT, &GPIO_InitStruct); HAL_GPIO_Init(TCA6416_SDA_PORT, &GPIO_InitStruct);
// 配置第二个芯片的SCL和SDA引脚为开漏输出
GPIO_InitStruct.Pin = TCA6416_SCL_PIN2 | TCA6416_SDA_PIN2;
HAL_GPIO_Init(TCA6416_SCL_PORT2, &GPIO_InitStruct);
// 初始状态设为高电平(实际由外部上拉电阻拉高) // 初始状态设为高电平(实际由外部上拉电阻拉高)
SCL_HIGH(); SCL_HIGH();
SDA_HIGH(); SDA_HIGH();
}
//第二条IIC总线初始化
void TCA6416_GPIO_Init2(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIOE时钟
__HAL_RCC_GPIOE_CLK_ENABLE();
//两个芯片挂一条总线上SDA PE4 SCL PE5
GPIO_InitStruct.Pin = TCA6416_SCL_PIN2 | TCA6416_SDA_PIN2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(TCA6416_SDA_PORT2, &GPIO_InitStruct);
// 初始状态设为高电平(实际由外部上拉电阻拉高)
SCL_HIGH2(); SCL_HIGH2();
SDA_HIGH2(); SDA_HIGH2();
} }
@ -421,7 +436,7 @@ uint8_t I2C_ReadByte2(void)
uint8_t TCA6416_Init2(void) uint8_t TCA6416_Init2(void)
{ {
// 初始化GPIO // 初始化GPIO
TCA6416_GPIO_Init(); TCA6416_GPIO_Init2();
// 增加延时以确保设备稳定 // 增加延时以确保设备稳定
HAL_Delay(10); HAL_Delay(10);

View File

@ -19,6 +19,9 @@
#include "tim.h" #include "tim.h"
#include "ad7124.h" #include "ad7124.h"
#include "tca6416_status.h" // 添加TCA6416状态头文件 #include "tca6416_status.h" // 添加TCA6416状态头文件
#include "DAC8568.h" // 添加DAC8568头文件
#include "dac161s997.h" // 添加DAC161S997头文件
#include "TCA6416.h" // 添加TCA6416头文件
// 添加test_adc_read_data变量定义 // 添加test_adc_read_data变量定义
uint8_t test_adc_read_data[74] = {0}; // 74字节的测试数据缓冲区 uint8_t test_adc_read_data[74] = {0}; // 74字节的测试数据缓冲区
@ -349,7 +352,7 @@ uint16_t handle_type_85(const uint8_t *body, uint16_t body_len, uint8_t *tx)
} }
uint16_t handle_type_86(const uint8_t *body, uint16_t body_len, uint8_t *tx) uint16_t handle_type_86(const uint8_t *body, uint16_t body_len, uint8_t *tx)
{ {
uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 22 + 2; // 帧头+帧长+源+目标+类型+22字节输出读取+校验 uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 24 + 2; // 帧头+帧长+源+目标+类型+24字节输出读取+校验
// 帧头 // 帧头
tx[0] = head_00; tx[0] = head_00;
@ -371,11 +374,11 @@ uint16_t total_len = 2 + 2 + 2 + 2 + 1 + 22 + 2; // 帧头+帧长+源+目标+类
tx[8] = reply_type; tx[8] = reply_type;
// 7字节使能状态直接复制 body 到 tx[9]~tx[15] // 7字节使能状态直接复制 body 到 tx[9]~tx[15]
memcpy(&tx[9], body, 22); // 确保 body 是22字节 memcpy(&tx[9], body, 24); // 确保 body 是24字节
// 校验和 // 校验和
uint16_t checksum = 0; uint16_t checksum = 0;
for (int i = 4; i < 32; ++i) // 4~31源地址+目标地址+类型+22字节) for (int i = 4; i < 28; ++i) // 4~27源地址+目标地址+类型+24字节)
{ {
checksum += tx[i]; checksum += tx[i];
} }
@ -647,8 +650,8 @@ static err_t tcpecho_recv_ble2(void *arg, struct tcp_pcb *tpcb, struct pbuf *p,
static err_t tcpecho_recv_control(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) static err_t tcpecho_recv_control(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{ {
uint8_t tcp_rx_data[128] = {0}; uint8_t tcp_rx_data[256] = {0};
uint8_t tcp_tx_data[128] = {0}; uint8_t tcp_tx_data[256] = {0};
uint8_t rx_data_len = 0; uint8_t rx_data_len = 0;
uint8_t tx_data_len = 0; uint8_t tx_data_len = 0;
@ -722,7 +725,63 @@ static err_t tcpecho_recv_control(void *arg, struct tcp_pcb *tpcb, struct pbuf *
break; break;
case 0x86://设置配置参数 case 0x86://设置配置参数
{ {
uint16_t body_len = 22; //22个字节表示的是设置的参数 uint16_t body_len = 24; //24个字节表示的是设置的参数8个通道每个通道2字节HART电流2字节比例阀4字节0-15数字量输出2字节
uint16_t dac_value;
uint16_t dac161s_value;
uint16_t digital_value;
// 处理DAC8568的8个通道输出
// 通道A (CH0)
dac_value = (tcp_rx_data[9] << 8) | tcp_rx_data[10];
DAC8568_WriteAndUpdate(CHANNEL_A, dac_value);
// 通道B (CH4)
dac_value = (tcp_rx_data[11] << 8) | tcp_rx_data[12];
DAC8568_WriteAndUpdate(CHANNEL_B, dac_value);
// 通道C (CH1)
dac_value = (tcp_rx_data[13] << 8) | tcp_rx_data[14];
DAC8568_WriteAndUpdate(CHANNEL_C, dac_value);
// 通道D (CH5)
dac_value = (tcp_rx_data[15] << 8) | tcp_rx_data[16];
DAC8568_WriteAndUpdate(CHANNEL_D, dac_value);
// 通道E (CH2)
dac_value = (tcp_rx_data[17] << 8) | tcp_rx_data[18];
DAC8568_WriteAndUpdate(CHANNEL_E, dac_value);
// 通道F (CH6)
dac_value = (tcp_rx_data[19] << 8) | tcp_rx_data[20];
DAC8568_WriteAndUpdate(CHANNEL_F, dac_value);
// 通道G (CH3)
dac_value = (tcp_rx_data[21] << 8) | tcp_rx_data[22];
DAC8568_WriteAndUpdate(CHANNEL_G, dac_value);
// 通道H (CH7)
dac_value = (tcp_rx_data[23] << 8) | tcp_rx_data[24];
DAC8568_WriteAndUpdate(CHANNEL_H, dac_value);
//HART电流输出
dac161s_value = (tcp_rx_data[25] << 8) | tcp_rx_data[26];
dac161s997_output(DAC161S997, dac161s_value);
//比例阀
//tcp_rx_data[27]
//tcp_rx_data[28]
//tcp_rx_data[29]
//tcp_rx_data[30]
// 数字量输出刷新第一个芯片的输出状态
TCA6416_WritePort(0, tcp_rx_data[31]); // 直接写入Port0的值8-15
osDelay(10);
TCA6416_WritePort(1, tcp_rx_data[32]); // 写入Port1的值0-7
osDelay(10);
// 保存设置的数据到adc_set_data数组
memcpy(adc_set_data, tcp_rx_data + 9, body_len);
reply_type = tcp_rx_data[8]; reply_type = tcp_rx_data[8];
tx_data_len = handle_type_86(adc_set_data, body_len, tcp_tx_data); tx_data_len = handle_type_86(adc_set_data, body_len, tcp_tx_data);
} }