TCA6416驱动测试OK
This commit is contained in:
parent
4585021528
commit
38a41744b9
|
@ -90,10 +90,21 @@ volatile uint32_t rts_pin_speed = 0; // RTS引脚速度
|
||||||
volatile uint32_t rts_pin_alternate = 0; // RTS引脚复用功能
|
volatile uint32_t rts_pin_alternate = 0; // RTS引脚复用功能
|
||||||
|
|
||||||
// 添加全局变量用于存储TCA6416引脚状态
|
// 添加全局变量用于存储TCA6416引脚状态
|
||||||
static volatile uint8_t tca6416_port0_status = 0; // 第一个TCA6416的Port0状态
|
volatile uint8_t tca6416_port0_status = 0; // 第一个TCA6416的Port0状态
|
||||||
static volatile uint8_t tca6416_port1_status = 0; // 第一个TCA6416的Port1状态
|
volatile uint8_t tca6416_port1_status = 0; // 第一个TCA6416的Port1状态
|
||||||
static volatile uint8_t tca6416_port2_status = 0; // 第二个TCA6416的Port0状态
|
volatile uint8_t tca6416_port2_status = 0; // 第二个TCA6416的Port0状态
|
||||||
static volatile uint8_t tca6416_port3_status = 0; // 第二个TCA6416的Port1状态
|
volatile uint8_t tca6416_port3_status = 0; // 第二个TCA6416的Port1状态
|
||||||
|
|
||||||
|
// 添加TCA6416测试相关的调试变量
|
||||||
|
volatile uint8_t tca6416_test_step = 0; // 当前测试步骤
|
||||||
|
volatile uint8_t tca6416_init_result = 0xFF; // 初始化结果
|
||||||
|
volatile uint8_t tca6416_write_data = 0; // 写入的数据
|
||||||
|
volatile uint8_t tca6416_read_data = 0; // 读取的数据
|
||||||
|
volatile uint8_t tca6416_error_count = 0; // 错误计数
|
||||||
|
volatile uint8_t tca6416_test_pattern = 0; // 测试模式
|
||||||
|
volatile uint8_t tca6416_port0_dir = 0; // Port0方向寄存器值
|
||||||
|
volatile uint8_t tca6416_port1_dir = 0; // Port1方向寄存器值
|
||||||
|
volatile uint8_t tca6416_i2c_ack_status = 0; // I2C应答状态
|
||||||
|
|
||||||
/* USER CODE END Variables */
|
/* USER CODE END Variables */
|
||||||
|
|
||||||
|
@ -112,6 +123,7 @@ extern struct tcp_pcb *server_pcb_control;
|
||||||
extern void tcp_abort(struct tcp_pcb *pcb);
|
extern void tcp_abort(struct tcp_pcb *pcb);
|
||||||
void start_usart6_test_task(void const *argument); // 添加USART6测试任务函数声明
|
void start_usart6_test_task(void const *argument); // 添加USART6测试任务函数声明
|
||||||
void start_tca6416_task(void const *argument); // 添加TCA6416任务函数声明
|
void start_tca6416_task(void const *argument); // 添加TCA6416任务函数声明
|
||||||
|
void test_tca6416_task(void const *argument); // 添加TCA6416测试任务函数声明
|
||||||
/* USER CODE END FunctionPrototypes */
|
/* USER CODE END FunctionPrototypes */
|
||||||
|
|
||||||
void start_tcp_task(void const *argument);
|
void start_tcp_task(void const *argument);
|
||||||
|
@ -207,9 +219,12 @@ void MX_FREERTOS_Init(void)
|
||||||
usart6_test_taskHandle = osThreadCreate(osThread(usart6_test_task), NULL);
|
usart6_test_taskHandle = osThreadCreate(osThread(usart6_test_task), NULL);
|
||||||
|
|
||||||
/* TCA6416任务 */
|
/* TCA6416任务 */
|
||||||
osThreadDef(tca6416_task, start_tca6416_task, osPriorityNormal, 0, 128);
|
//osThreadDef(tca6416_task, start_tca6416_task, osPriorityNormal, 0, 128);
|
||||||
tca6416_taskHandle = osThreadCreate(osThread(tca6416_task), NULL);
|
// tca6416_taskHandle = osThreadCreate(osThread(tca6416_task), NULL);
|
||||||
|
/* TCA6416测试任务 */
|
||||||
|
|
||||||
|
osThreadDef(tca6416_task, test_tca6416_task, osPriorityNormal, 0, 128);
|
||||||
|
tca6416_taskHandle = osThreadCreate(osThread(tca6416_task), NULL);
|
||||||
/* USER CODE BEGIN RTOS_THREADS */
|
/* USER CODE BEGIN RTOS_THREADS */
|
||||||
/* add threads, ... */
|
/* add threads, ... */
|
||||||
/* USER CODE END RTOS_THREADS */
|
/* USER CODE END RTOS_THREADS */
|
||||||
|
@ -569,10 +584,7 @@ void start_usart6_dma_test_task(void const *argument)
|
||||||
void start_tca6416_task(void const *argument)
|
void start_tca6416_task(void const *argument)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN start_tca6416_task */
|
/* USER CODE BEGIN start_tca6416_task */
|
||||||
uint8_t port0_data = 0;
|
uint8_t port0_data, port1_data;
|
||||||
uint8_t port1_data = 0;
|
|
||||||
uint8_t port2_data = 0;
|
|
||||||
uint8_t port3_data = 0;
|
|
||||||
|
|
||||||
// 初始化第一个TCA6416
|
// 初始化第一个TCA6416
|
||||||
if(TCA6416_Init() != 0)
|
if(TCA6416_Init() != 0)
|
||||||
|
@ -580,52 +592,216 @@ void start_tca6416_task(void const *argument)
|
||||||
Error_Handler();
|
Error_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置第一个TCA6416端口方向
|
// 初始化第二个TCA6416
|
||||||
// Port0: 全输入
|
if(TCA6416_Init2() != 0)
|
||||||
TCA6416_SetPortDirection(0, 0xFF); // 0xFF = 11111111b
|
{
|
||||||
// Port1: 全输入
|
Error_Handler();
|
||||||
TCA6416_SetPortDirection(1, 0xFF); // 0xFF = 11111111b
|
}
|
||||||
|
|
||||||
// 初始化第二个TCA6416 (使用SCL_PIN2和SDA_PIN2)
|
// 设置两个芯片的所有端口为输入
|
||||||
// 注意:这里需要修改TCA6416_Init函数以支持第二个芯片
|
if(TCA6416_SetPortDirection(0, 0xFF) != 0) Error_Handler();
|
||||||
// 暂时使用相同的初始化函数,但实际使用时需要修改
|
if(TCA6416_SetPortDirection(1, 0xFF) != 0) Error_Handler();
|
||||||
|
if(TCA6416_SetPortDirection2(0, 0xFF) != 0) Error_Handler();
|
||||||
|
if(TCA6416_SetPortDirection2(1, 0xFF) != 0) Error_Handler();
|
||||||
|
|
||||||
// 配置第二个TCA6416端口方向
|
|
||||||
// Port0: 全输入
|
|
||||||
TCA6416_SetPortDirection(0, 0xFF); // 0xFF = 11111111b
|
|
||||||
// Port1: 全输入
|
|
||||||
TCA6416_SetPortDirection(1, 0xFF); // 0xFF = 11111111b
|
|
||||||
|
|
||||||
/* Infinite loop */
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
// 读取第一个TCA6416的输入端口状态
|
// 读取第一个芯片的输入状态
|
||||||
if(TCA6416_ReadPort(0, &port0_data) == 0)
|
if(TCA6416_ReadPort(0, &port0_data) == 0)
|
||||||
{
|
{
|
||||||
tca6416_port0_status = port0_data;
|
tca6416_port0_status = port0_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(TCA6416_ReadPort(1, &port1_data) == 0)
|
if(TCA6416_ReadPort(1, &port1_data) == 0)
|
||||||
{
|
{
|
||||||
tca6416_port1_status = port1_data;
|
tca6416_port1_status = port1_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取第二个TCA6416的输入端口状态
|
// 读取第二个芯片的输入状态
|
||||||
// 注意:这里需要修改TCA6416_ReadPort函数以支持第二个芯片
|
if(TCA6416_ReadPort2(0, &port0_data) == 0)
|
||||||
// 暂时使用相同的读取函数,但实际使用时需要修改
|
|
||||||
if(TCA6416_ReadPort(0, &port2_data) == 0)
|
|
||||||
{
|
{
|
||||||
tca6416_port2_status = port2_data;
|
tca6416_port2_status = port0_data;
|
||||||
|
}
|
||||||
|
if(TCA6416_ReadPort2(1, &port1_data) == 0)
|
||||||
|
{
|
||||||
|
tca6416_port3_status = port1_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(TCA6416_ReadPort(1, &port3_data) == 0)
|
osDelay(100); // 100ms读取一次
|
||||||
{
|
|
||||||
tca6416_port3_status = port3_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 任务延时
|
|
||||||
vTaskDelay(10); // 10ms延时
|
|
||||||
}
|
}
|
||||||
/* USER CODE END start_tca6416_task */
|
/* USER CODE END start_tca6416_task */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_tca6416_task(void const *argument)
|
||||||
|
{
|
||||||
|
/* USER CODE BEGIN test_tca6416_task */
|
||||||
|
uint8_t ret = 0;
|
||||||
|
uint8_t test_patterns[] = {0x00, 0xFF, 0xAA, 0x55, 0x0F, 0xF0, 0x5A, 0xA5};
|
||||||
|
uint8_t pattern_index = 0;
|
||||||
|
uint8_t addr_scan_result[8] = {0}; // 存储地址扫描结果
|
||||||
|
|
||||||
|
// 等待系统稳定
|
||||||
|
osDelay(100);
|
||||||
|
|
||||||
|
// 步骤0: I2C地址扫描
|
||||||
|
tca6416_test_step = 0;
|
||||||
|
for(uint8_t addr = 0x20; addr <= 0x27; addr++)
|
||||||
|
{
|
||||||
|
I2C_Start();
|
||||||
|
ret = I2C_SendByte(addr << 1);
|
||||||
|
I2C_Stop();
|
||||||
|
addr_scan_result[addr - 0x20] = ret; // 0=ACK, 1=NACK
|
||||||
|
osDelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤1: 初始化TCA6416
|
||||||
|
tca6416_test_step = 1;
|
||||||
|
tca6416_init_result = TCA6416_Init();
|
||||||
|
|
||||||
|
if(tca6416_init_result != 0)
|
||||||
|
{
|
||||||
|
// 初始化失败,停留在此步骤
|
||||||
|
tca6416_error_count++;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
osDelay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化成功,继续测试
|
||||||
|
osDelay(50);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
// 步骤2: 设置Port0为输出,Port1为输入
|
||||||
|
tca6416_test_step = 2;
|
||||||
|
tca6416_port0_dir = 0x00; // 0=输出
|
||||||
|
tca6416_port1_dir = 0xFF; // 1=输入
|
||||||
|
|
||||||
|
ret = TCA6416_SetPortDirection(0, tca6416_port0_dir);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
ret = TCA6416_SetPortDirection(1, tca6416_port1_dir);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 步骤3: 写入测试模式到Port0
|
||||||
|
tca6416_test_step = 3;
|
||||||
|
tca6416_test_pattern = test_patterns[pattern_index];
|
||||||
|
tca6416_write_data = tca6416_test_pattern;
|
||||||
|
|
||||||
|
ret = TCA6416_WritePort(0, tca6416_write_data);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 步骤4: 读取Port0的值(验证写入)
|
||||||
|
tca6416_test_step = 4;
|
||||||
|
ret = TCA6416_ReadPort(0, &tca6416_read_data);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 更新状态变量
|
||||||
|
tca6416_port0_status = tca6416_read_data;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 步骤5: 读取Port1的输入状态
|
||||||
|
tca6416_test_step = 5;
|
||||||
|
ret = TCA6416_ReadPort(1, &tca6416_read_data);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 更新状态变量
|
||||||
|
tca6416_port1_status = tca6416_read_data;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 步骤6: 测试单个引脚操作
|
||||||
|
tca6416_test_step = 6;
|
||||||
|
for(uint8_t pin = 0; pin < 8; pin++)
|
||||||
|
{
|
||||||
|
// 设置单个引脚为高
|
||||||
|
ret = TCA6416_WritePin(0, pin, 1);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(5);
|
||||||
|
|
||||||
|
// 读取验证
|
||||||
|
uint8_t pin_state = 0;
|
||||||
|
ret = TCA6416_ReadPin(0, pin, &pin_state);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(5);
|
||||||
|
|
||||||
|
// 设置单个引脚为低
|
||||||
|
ret = TCA6416_WritePin(0, pin, 0);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤7: 测试极性反转功能
|
||||||
|
tca6416_test_step = 7;
|
||||||
|
ret = TCA6416_SetPortPolarity(0, 0xFF); // 反转所有位
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 读取并验证极性反转效果
|
||||||
|
ret = TCA6416_ReadPort(0, &tca6416_read_data);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 恢复正常极性
|
||||||
|
ret = TCA6416_SetPortPolarity(0, 0x00);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
tca6416_error_count++;
|
||||||
|
tca6416_i2c_ack_status = ret;
|
||||||
|
}
|
||||||
|
osDelay(10);
|
||||||
|
|
||||||
|
// 切换到下一个测试模式
|
||||||
|
pattern_index = (pattern_index + 1) % (sizeof(test_patterns) / sizeof(test_patterns[0]));
|
||||||
|
|
||||||
|
// 延时后继续下一轮测试
|
||||||
|
osDelay(500);
|
||||||
|
}
|
||||||
|
/* USER CODE END test_tca6416_task */
|
||||||
|
}
|
|
@ -93,11 +93,11 @@ void MX_GPIO_Init(void)
|
||||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pins : PEPin PEPin PEPin PEPin */
|
/*Configure GPIO pins : PEPin PEPin PEPin PEPin */
|
||||||
GPIO_InitStruct.Pin = LED3_Y_Pin|LED2_R_Pin|LED2_G_Pin|LED2_Y_Pin;
|
// GPIO_InitStruct.Pin = LED3_Y_Pin|LED2_R_Pin|LED2_G_Pin|LED2_Y_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
// GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
// GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
|
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
|
||||||
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
|
// HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pin : PtPin */
|
/*Configure GPIO pin : PtPin */
|
||||||
GPIO_InitStruct.Pin = EC11_KEY_Pin;
|
GPIO_InitStruct.Pin = EC11_KEY_Pin;
|
||||||
|
@ -172,11 +172,11 @@ void MX_GPIO_Init(void)
|
||||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pins : PBPin PBPin */
|
/*Configure GPIO pins : PBPin PBPin */
|
||||||
GPIO_InitStruct.Pin = DAC1_CS_Pin|DAC2_CS_Pin;
|
// GPIO_InitStruct.Pin = DAC1_CS_Pin|DAC2_CS_Pin;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
// GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
// GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
// HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
|
||||||
/*Configure GPIO pin : PtPin */
|
/*Configure GPIO pin : PtPin */
|
||||||
GPIO_InitStruct.Pin = ADC_CS_Pin;
|
GPIO_InitStruct.Pin = ADC_CS_Pin;
|
||||||
|
|
|
@ -265,6 +265,36 @@
|
||||||
<WinNumber>1</WinNumber>
|
<WinNumber>1</WinNumber>
|
||||||
<ItemText>uart6_stop_bits</ItemText>
|
<ItemText>uart6_stop_bits</ItemText>
|
||||||
</Ww>
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>23</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_init_result</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>24</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_write_data</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>25</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_read_data</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>26</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_error_count</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>27</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_test_pattern</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>28</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>tca6416_i2c_ack_status</ItemText>
|
||||||
|
</Ww>
|
||||||
</WatchWindow1>
|
</WatchWindow1>
|
||||||
<Tracepoint>
|
<Tracepoint>
|
||||||
<THDelay>0</THDelay>
|
<THDelay>0</THDelay>
|
||||||
|
@ -1880,7 +1910,7 @@
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>User/board</GroupName>
|
<GroupName>User/board</GroupName>
|
||||||
<tvExp>1</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<cbSel>0</cbSel>
|
<cbSel>0</cbSel>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __TCA6416_H
|
#ifndef __TCA6416_H
|
||||||
#define __TCA6416_H
|
#define __TCA6416_H
|
||||||
|
|
||||||
#include "stm32f4xx_hal.h" // 只包含基本的 HAL 头文件
|
#include "main.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* GPIO定义 */
|
/* GPIO定义 */
|
||||||
|
@ -9,13 +9,14 @@
|
||||||
#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)
|
||||||
|
#define TCA6416_ADDR2 0x21 // 第二个芯片地址 (A0=1, A1=A2=GND)
|
||||||
|
|
||||||
/* 寄存器地址定义 */
|
/* 寄存器地址定义 */
|
||||||
#define TCA6416_INPUT_PORT0 0x00 // 输入端口0
|
#define TCA6416_INPUT_PORT0 0x00 // 输入端口0
|
||||||
|
@ -28,32 +29,69 @@
|
||||||
#define TCA6416_POL_INV_PORT1 0x05 // 极性反转端口1
|
#define TCA6416_POL_INV_PORT1 0x05 // 极性反转端口1
|
||||||
|
|
||||||
/* 软件I2C延时定义 */
|
/* 软件I2C延时定义 */
|
||||||
#define I2C_DELAY() HAL_Delay(1) // 可以根据实际需要调整延时
|
#define I2C_DELAY() HAL_Delay(5) // 增加延时时间到5ms
|
||||||
|
|
||||||
/* 软件I2C基本操作函数 */
|
/* 第一个芯片的软件I2C基本操作函数 */
|
||||||
#define SCL_HIGH() HAL_GPIO_WritePin(TCA6416_SCL_PORT, TCA6416_SCL_PIN, GPIO_PIN_SET)
|
#define SCL_HIGH() HAL_GPIO_WritePin(TCA6416_SCL_PORT, TCA6416_SCL_PIN, GPIO_PIN_SET)
|
||||||
#define SCL_LOW() HAL_GPIO_WritePin(TCA6416_SCL_PORT, TCA6416_SCL_PIN, GPIO_PIN_RESET)
|
#define SCL_LOW() HAL_GPIO_WritePin(TCA6416_SCL_PORT, TCA6416_SCL_PIN, GPIO_PIN_RESET)
|
||||||
#define SDA_HIGH() HAL_GPIO_WritePin(TCA6416_SDA_PORT, TCA6416_SDA_PIN, GPIO_PIN_SET)
|
#define SDA_HIGH() HAL_GPIO_WritePin(TCA6416_SDA_PORT, TCA6416_SDA_PIN, GPIO_PIN_SET)
|
||||||
#define SDA_LOW() HAL_GPIO_WritePin(TCA6416_SDA_PORT, TCA6416_SDA_PIN, GPIO_PIN_RESET)
|
#define SDA_LOW() HAL_GPIO_WritePin(TCA6416_SDA_PORT, TCA6416_SDA_PIN, GPIO_PIN_RESET)
|
||||||
#define SDA_READ() HAL_GPIO_ReadPin(TCA6416_SDA_PORT, TCA6416_SDA_PIN)
|
#define SDA_READ() HAL_GPIO_ReadPin(TCA6416_SDA_PORT, TCA6416_SDA_PIN)
|
||||||
|
|
||||||
|
/* SDA输入/输出模式切换宏 */
|
||||||
|
#define SDA_INPUT_MODE() do { \
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
|
||||||
|
GPIO_InitStruct.Pin = TCA6416_SDA_PIN; \
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
|
||||||
|
GPIO_InitStruct.Pull = GPIO_NOPULL; \
|
||||||
|
HAL_GPIO_Init(TCA6416_SDA_PORT, &GPIO_InitStruct); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define SDA_OUTPUT_MODE() do { \
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct = {0}; \
|
||||||
|
GPIO_InitStruct.Pin = TCA6416_SDA_PIN; \
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; \
|
||||||
|
GPIO_InitStruct.Pull = GPIO_NOPULL; \
|
||||||
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; \
|
||||||
|
HAL_GPIO_Init(TCA6416_SDA_PORT, &GPIO_InitStruct); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* 第二个芯片的软件I2C基本操作函数 */
|
||||||
|
#define SCL_HIGH2() HAL_GPIO_WritePin(TCA6416_SCL_PORT2, TCA6416_SCL_PIN2, GPIO_PIN_SET)
|
||||||
|
#define SCL_LOW2() HAL_GPIO_WritePin(TCA6416_SCL_PORT2, TCA6416_SCL_PIN2, GPIO_PIN_RESET)
|
||||||
|
#define SDA_HIGH2() HAL_GPIO_WritePin(TCA6416_SDA_PORT2, TCA6416_SDA_PIN2, GPIO_PIN_SET)
|
||||||
|
#define SDA_LOW2() HAL_GPIO_WritePin(TCA6416_SDA_PORT2, TCA6416_SDA_PIN2, GPIO_PIN_RESET)
|
||||||
|
#define SDA_READ2() HAL_GPIO_ReadPin(TCA6416_SDA_PORT2, TCA6416_SDA_PIN2)
|
||||||
|
|
||||||
/* 函数声明 */
|
/* 函数声明 */
|
||||||
void TCA6416_GPIO_Init(void);
|
void TCA6416_GPIO_Init(void);
|
||||||
uint8_t TCA6416_Init(void);
|
uint8_t TCA6416_Init(void);
|
||||||
|
uint8_t TCA6416_Init2(void); // 第二个芯片的初始化函数
|
||||||
uint8_t TCA6416_WritePort(uint8_t port, uint8_t data);
|
uint8_t TCA6416_WritePort(uint8_t port, uint8_t data);
|
||||||
|
uint8_t TCA6416_WritePort2(uint8_t port, uint8_t data); // 第二个芯片的写端口函数
|
||||||
uint8_t TCA6416_ReadPort(uint8_t port, uint8_t *data);
|
uint8_t TCA6416_ReadPort(uint8_t port, uint8_t *data);
|
||||||
|
uint8_t TCA6416_ReadPort2(uint8_t port, uint8_t *data); // 第二个芯片的读端口函数
|
||||||
uint8_t TCA6416_SetPortDirection(uint8_t port, uint8_t direction);
|
uint8_t TCA6416_SetPortDirection(uint8_t port, uint8_t direction);
|
||||||
|
uint8_t TCA6416_SetPortDirection2(uint8_t port, uint8_t direction); // 第二个芯片的设置方向函数
|
||||||
uint8_t TCA6416_SetPortPolarity(uint8_t port, uint8_t polarity);
|
uint8_t TCA6416_SetPortPolarity(uint8_t port, uint8_t polarity);
|
||||||
|
uint8_t TCA6416_SetPortPolarity2(uint8_t port, uint8_t polarity); // 第二个芯片的设置极性函数
|
||||||
uint8_t TCA6416_WritePin(uint8_t port, uint8_t pin, uint8_t state);
|
uint8_t TCA6416_WritePin(uint8_t port, uint8_t pin, uint8_t state);
|
||||||
uint8_t TCA6416_ReadPin(uint8_t port, uint8_t pin, uint8_t *state);
|
uint8_t TCA6416_ReadPin(uint8_t port, uint8_t pin, uint8_t *state);
|
||||||
|
|
||||||
/* 软件I2C底层函数 */
|
/* 软件I2C底层函数 */
|
||||||
void I2C_Start(void);
|
void I2C_Start(void);
|
||||||
|
void I2C_Start2(void); // 第二个芯片的I2C起始信号
|
||||||
void I2C_Stop(void);
|
void I2C_Stop(void);
|
||||||
|
void I2C_Stop2(void); // 第二个芯片的I2C停止信号
|
||||||
void I2C_Ack(void);
|
void I2C_Ack(void);
|
||||||
|
void I2C_Ack2(void); // 第二个芯片的I2C应答
|
||||||
void I2C_NAck(void);
|
void I2C_NAck(void);
|
||||||
|
void I2C_NAck2(void); // 第二个芯片的I2C非应答
|
||||||
uint8_t I2C_WaitAck(void);
|
uint8_t I2C_WaitAck(void);
|
||||||
void I2C_SendByte(uint8_t byte);
|
uint8_t I2C_WaitAck2(void); // 第二个芯片的等待应答
|
||||||
|
uint8_t I2C_SendByte(uint8_t byte); // 修正返回值类型
|
||||||
|
void I2C_SendByte2(uint8_t byte); // 第二个芯片的发送字节
|
||||||
uint8_t I2C_ReadByte(void);
|
uint8_t I2C_ReadByte(void);
|
||||||
|
uint8_t I2C_ReadByte2(void); // 第二个芯片的读取字节
|
||||||
|
|
||||||
#endif /* __TCA6416_H */
|
#endif /* __TCA6416_H */
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __TCA6416_STATUS_H
|
||||||
|
#define __TCA6416_STATUS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 声明TCA6416状态变量
|
||||||
|
extern volatile uint8_t tca6416_port0_status; // 第一个TCA6416的Port0状态
|
||||||
|
extern volatile uint8_t tca6416_port1_status; // 第一个TCA6416的Port1状态
|
||||||
|
extern volatile uint8_t tca6416_port2_status; // 第二个TCA6416的Port0状态
|
||||||
|
extern volatile uint8_t tca6416_port3_status; // 第二个TCA6416的Port1状态
|
||||||
|
|
||||||
|
#endif /* __TCA6416_STATUS_H */
|
|
@ -1,4 +1,6 @@
|
||||||
|
#include "main.h"
|
||||||
#include "TCA6416.h"
|
#include "TCA6416.h"
|
||||||
|
#include "stm32f4xx_hal.h" // 更新HAL库头文件路径
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化TCA6416的GPIO
|
* @brief 初始化TCA6416的GPIO
|
||||||
|
@ -10,16 +12,22 @@ void TCA6416_GPIO_Init(void)
|
||||||
// 使能GPIOE时钟
|
// 使能GPIOE时钟
|
||||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||||
|
|
||||||
// 配置SCL和SDA引脚
|
// 配置第一个芯片的SCL和SDA引脚为开漏输出
|
||||||
GPIO_InitStruct.Pin = TCA6416_SCL_PIN | TCA6416_SDA_PIN;
|
GPIO_InitStruct.Pin = TCA6416_SCL_PIN | TCA6416_SDA_PIN;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无内部上拉,依赖外部上拉
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||||
HAL_GPIO_Init(TCA6416_SCL_PORT, &GPIO_InitStruct);
|
HAL_GPIO_Init(TCA6416_SCL_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();
|
||||||
|
SCL_HIGH2();
|
||||||
|
SDA_HIGH2();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,12 +35,13 @@ void TCA6416_GPIO_Init(void)
|
||||||
*/
|
*/
|
||||||
void I2C_Start(void)
|
void I2C_Start(void)
|
||||||
{
|
{
|
||||||
|
SDA_OUTPUT_MODE(); // 确保SDA为输出模式
|
||||||
SDA_HIGH();
|
SDA_HIGH();
|
||||||
SCL_HIGH();
|
SCL_HIGH();
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
SDA_LOW();
|
SDA_LOW(); // SDA下降沿(SCL为高)
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
SCL_LOW();
|
SCL_LOW(); // 拉低SCL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,12 +49,13 @@ void I2C_Start(void)
|
||||||
*/
|
*/
|
||||||
void I2C_Stop(void)
|
void I2C_Stop(void)
|
||||||
{
|
{
|
||||||
|
SDA_OUTPUT_MODE(); // 确保SDA为输出模式
|
||||||
SCL_LOW();
|
SCL_LOW();
|
||||||
SDA_LOW();
|
SDA_LOW();
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
SCL_HIGH();
|
SCL_HIGH();
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
SDA_HIGH();
|
SDA_HIGH(); // SDA上升沿(SCL为高)
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +95,7 @@ uint8_t I2C_WaitAck(void)
|
||||||
|
|
||||||
SCL_LOW();
|
SCL_LOW();
|
||||||
SDA_HIGH();
|
SDA_HIGH();
|
||||||
|
SDA_INPUT_MODE();
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
SCL_HIGH();
|
SCL_HIGH();
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
|
@ -92,6 +103,7 @@ uint8_t I2C_WaitAck(void)
|
||||||
ack = SDA_READ() ? 1 : 0;
|
ack = SDA_READ() ? 1 : 0;
|
||||||
|
|
||||||
SCL_LOW();
|
SCL_LOW();
|
||||||
|
SDA_OUTPUT_MODE();
|
||||||
return ack;
|
return ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +111,13 @@ uint8_t I2C_WaitAck(void)
|
||||||
* @brief 软件I2C发送一个字节
|
* @brief 软件I2C发送一个字节
|
||||||
* @param byte: 要发送的字节
|
* @param byte: 要发送的字节
|
||||||
*/
|
*/
|
||||||
void I2C_SendByte(uint8_t byte)
|
uint8_t I2C_SendByte(uint8_t byte)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
SCL_LOW();
|
SCL_LOW();
|
||||||
|
I2C_DELAY();
|
||||||
if(byte & 0x80)
|
if(byte & 0x80)
|
||||||
SDA_HIGH();
|
SDA_HIGH();
|
||||||
else
|
else
|
||||||
|
@ -116,6 +128,16 @@ void I2C_SendByte(uint8_t byte)
|
||||||
I2C_DELAY();
|
I2C_DELAY();
|
||||||
}
|
}
|
||||||
SCL_LOW();
|
SCL_LOW();
|
||||||
|
// 释放SDA,准备接收ACK
|
||||||
|
SDA_HIGH();
|
||||||
|
SDA_INPUT_MODE();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH();
|
||||||
|
I2C_DELAY();
|
||||||
|
uint8_t ack = SDA_READ() ? 1 : 0; // 0=ACK, 1=NACK
|
||||||
|
SCL_LOW();
|
||||||
|
SDA_OUTPUT_MODE();
|
||||||
|
return ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,6 +171,7 @@ uint8_t TCA6416_Init(void)
|
||||||
{
|
{
|
||||||
// 初始化GPIO
|
// 初始化GPIO
|
||||||
TCA6416_GPIO_Init();
|
TCA6416_GPIO_Init();
|
||||||
|
HAL_Delay(50);
|
||||||
|
|
||||||
// 默认将所有引脚设置为输入
|
// 默认将所有引脚设置为输入
|
||||||
if(TCA6416_SetPortDirection(0, 0xFF) != 0) return 1;
|
if(TCA6416_SetPortDirection(0, 0xFF) != 0) return 1;
|
||||||
|
@ -176,14 +199,11 @@ uint8_t TCA6416_WritePort(uint8_t port, uint8_t data)
|
||||||
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||||||
|
|
||||||
I2C_Start();
|
I2C_Start();
|
||||||
I2C_SendByte(TCA6416_ADDR << 1); // 写地址
|
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(reg_addr); // 寄存器地址
|
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(data); // 数据
|
if(I2C_SendByte(data)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_Stop();
|
I2C_Stop();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -200,15 +220,12 @@ uint8_t TCA6416_ReadPort(uint8_t port, uint8_t *data)
|
||||||
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
||||||
|
|
||||||
I2C_Start();
|
I2C_Start();
|
||||||
I2C_SendByte(TCA6416_ADDR << 1); // 写地址
|
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(reg_addr); // 寄存器地址
|
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_Start();
|
I2C_Start();
|
||||||
I2C_SendByte((TCA6416_ADDR << 1) | 0x01); // 读地址
|
if(I2C_SendByte((TCA6416_ADDR << 1) | 0x01)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
*data = I2C_ReadByte(); // 读取数据
|
*data = I2C_ReadByte(); // 读取数据
|
||||||
I2C_NAck();
|
I2C_NAck();
|
||||||
|
@ -228,14 +245,11 @@ uint8_t TCA6416_SetPortDirection(uint8_t port, uint8_t direction)
|
||||||
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
||||||
|
|
||||||
I2C_Start();
|
I2C_Start();
|
||||||
I2C_SendByte(TCA6416_ADDR << 1); // 写地址
|
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(reg_addr); // 寄存器地址
|
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(direction); // 方向设置
|
if(I2C_SendByte(direction)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_Stop();
|
I2C_Stop();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -252,14 +266,11 @@ uint8_t TCA6416_SetPortPolarity(uint8_t port, uint8_t polarity)
|
||||||
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
||||||
|
|
||||||
I2C_Start();
|
I2C_Start();
|
||||||
I2C_SendByte(TCA6416_ADDR << 1); // 写地址
|
if(I2C_SendByte(TCA6416_ADDR << 1)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(reg_addr); // 寄存器地址
|
if(I2C_SendByte(reg_addr)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_SendByte(polarity); // 极性设置
|
if(I2C_SendByte(polarity)) { I2C_Stop(); return 1; } // 直接使用返回值
|
||||||
if(I2C_WaitAck()) { I2C_Stop(); return 1; }
|
|
||||||
|
|
||||||
I2C_Stop();
|
I2C_Stop();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -306,3 +317,228 @@ uint8_t TCA6416_ReadPin(uint8_t port, uint8_t pin, uint8_t *state)
|
||||||
*state = (port_data >> pin) & 0x01;
|
*state = (port_data >> pin) & 0x01;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 第二个芯片的I2C操作函数 */
|
||||||
|
void I2C_Start2(void)
|
||||||
|
{
|
||||||
|
SDA_HIGH2();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SDA_LOW2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_LOW2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_Stop2(void)
|
||||||
|
{
|
||||||
|
SCL_LOW2();
|
||||||
|
SDA_LOW2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SDA_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_Ack2(void)
|
||||||
|
{
|
||||||
|
SCL_LOW2();
|
||||||
|
SDA_LOW2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_LOW2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_NAck2(void)
|
||||||
|
{
|
||||||
|
SCL_LOW2();
|
||||||
|
SDA_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_LOW2();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2C_WaitAck2(void)
|
||||||
|
{
|
||||||
|
uint8_t ack;
|
||||||
|
|
||||||
|
SCL_LOW2();
|
||||||
|
SDA_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
|
||||||
|
ack = SDA_READ2() ? 1 : 0;
|
||||||
|
|
||||||
|
SCL_LOW2();
|
||||||
|
return ack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_SendByte2(uint8_t byte)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
SCL_LOW2();
|
||||||
|
if(byte & 0x80)
|
||||||
|
SDA_HIGH2();
|
||||||
|
else
|
||||||
|
SDA_LOW2();
|
||||||
|
byte <<= 1;
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
I2C_DELAY();
|
||||||
|
}
|
||||||
|
SCL_LOW2();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2C_ReadByte2(void)
|
||||||
|
{
|
||||||
|
uint8_t i, byte = 0;
|
||||||
|
|
||||||
|
SDA_HIGH2();
|
||||||
|
for(i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
SCL_LOW2();
|
||||||
|
I2C_DELAY();
|
||||||
|
SCL_HIGH2();
|
||||||
|
byte <<= 1;
|
||||||
|
if(SDA_READ2())
|
||||||
|
byte |= 0x01;
|
||||||
|
I2C_DELAY();
|
||||||
|
}
|
||||||
|
SCL_LOW2();
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化第二个TCA6416
|
||||||
|
* @retval 0:成功 1:失败
|
||||||
|
*/
|
||||||
|
uint8_t TCA6416_Init2(void)
|
||||||
|
{
|
||||||
|
// 初始化GPIO
|
||||||
|
TCA6416_GPIO_Init();
|
||||||
|
|
||||||
|
// 增加延时以确保设备稳定
|
||||||
|
HAL_Delay(10);
|
||||||
|
|
||||||
|
// 默认将所有引脚设置为输入
|
||||||
|
if(TCA6416_SetPortDirection2(0, 0xFF) != 0) return 1;
|
||||||
|
if(TCA6416_SetPortDirection2(1, 0xFF) != 0) return 1;
|
||||||
|
|
||||||
|
// 设置默认输出值为0
|
||||||
|
if(TCA6416_WritePort2(0, 0x00) != 0) return 1;
|
||||||
|
if(TCA6416_WritePort2(1, 0x00) != 0) return 1;
|
||||||
|
|
||||||
|
// 设置默认极性(非反转)
|
||||||
|
if(TCA6416_SetPortPolarity2(0, 0x00) != 0) return 1;
|
||||||
|
if(TCA6416_SetPortPolarity2(1, 0x00) != 0) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 向第二个TCA6416的端口写入数据
|
||||||
|
* @param port: 端口号(0或1)
|
||||||
|
* @param data: 要写入的数据
|
||||||
|
* @retval 0:成功 1:失败
|
||||||
|
*/
|
||||||
|
uint8_t TCA6416_WritePort2(uint8_t port, uint8_t data)
|
||||||
|
{
|
||||||
|
uint8_t reg_addr = (port == 0) ? TCA6416_OUTPUT_PORT0 : TCA6416_OUTPUT_PORT1;
|
||||||
|
|
||||||
|
I2C_Start2();
|
||||||
|
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(reg_addr); // 寄存器地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(data); // 数据
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_Stop2();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从第二个TCA6416的端口读取数据
|
||||||
|
* @param port: 端口号(0或1)
|
||||||
|
* @param data: 存储读取数据的指针
|
||||||
|
* @retval 0:成功 1:失败
|
||||||
|
*/
|
||||||
|
uint8_t TCA6416_ReadPort2(uint8_t port, uint8_t *data)
|
||||||
|
{
|
||||||
|
uint8_t reg_addr = (port == 0) ? TCA6416_INPUT_PORT0 : TCA6416_INPUT_PORT1;
|
||||||
|
|
||||||
|
I2C_Start2();
|
||||||
|
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(reg_addr); // 寄存器地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_Start2();
|
||||||
|
I2C_SendByte2((TCA6416_ADDR2 << 1) | 0x01); // 读地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
*data = I2C_ReadByte2(); // 读取数据
|
||||||
|
I2C_NAck2();
|
||||||
|
|
||||||
|
I2C_Stop2();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置第二个TCA6416的端口方向
|
||||||
|
* @param port: 端口号(0或1)
|
||||||
|
* @param direction: 0 = 输出, 1 = 输入
|
||||||
|
* @retval 0:成功 1:失败
|
||||||
|
*/
|
||||||
|
uint8_t TCA6416_SetPortDirection2(uint8_t port, uint8_t direction)
|
||||||
|
{
|
||||||
|
uint8_t reg_addr = (port == 0) ? TCA6416_CONFIG_PORT0 : TCA6416_CONFIG_PORT1;
|
||||||
|
|
||||||
|
I2C_Start2();
|
||||||
|
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(reg_addr); // 寄存器地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(direction); // 方向设置
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_Stop2();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置第二个TCA6416的端口极性
|
||||||
|
* @param port: 端口号(0或1)
|
||||||
|
* @param polarity: 0 = 非反转, 1 = 反转
|
||||||
|
* @retval 0:成功 1:失败
|
||||||
|
*/
|
||||||
|
uint8_t TCA6416_SetPortPolarity2(uint8_t port, uint8_t polarity)
|
||||||
|
{
|
||||||
|
uint8_t reg_addr = (port == 0) ? TCA6416_POL_INV_PORT0 : TCA6416_POL_INV_PORT1;
|
||||||
|
|
||||||
|
I2C_Start2();
|
||||||
|
I2C_SendByte2(TCA6416_ADDR2 << 1); // 写地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(reg_addr); // 寄存器地址
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_SendByte2(polarity); // 极性设置
|
||||||
|
if(I2C_WaitAck2()) { I2C_Stop2(); return 1; }
|
||||||
|
|
||||||
|
I2C_Stop2();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "user_gpio.h"
|
#include "user_gpio.h"
|
||||||
#include "tim.h"
|
#include "tim.h"
|
||||||
#include "ad7124.h"
|
#include "ad7124.h"
|
||||||
|
#include "tca6416_status.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字节的测试数据缓冲区
|
||||||
|
@ -95,12 +96,6 @@ uint8_t adc_set_data[22] = {
|
||||||
0x0D,0xF0,// 比例阀2输出高字节, 比例阀2输出低字节
|
0x0D,0xF0,// 比例阀2输出高字节, 比例阀2输出低字节
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加外部声明
|
|
||||||
extern volatile uint8_t tca6416_port0_status;
|
|
||||||
extern volatile uint8_t tca6416_port1_status;
|
|
||||||
extern volatile uint8_t tca6416_port2_status;
|
|
||||||
extern volatile uint8_t tca6416_port3_status;
|
|
||||||
|
|
||||||
// 校验和函数
|
// 校验和函数
|
||||||
uint8_t calc_checksum(const uint8_t *data, uint8_t start, uint8_t end) {
|
uint8_t calc_checksum(const uint8_t *data, uint8_t start, uint8_t end) {
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
|
@ -405,29 +400,27 @@ uint16_t handle_type_87(const uint8_t *body, uint16_t body_len, uint8_t *tx)
|
||||||
tx[8] = reply_type;
|
tx[8] = reply_type;
|
||||||
|
|
||||||
// 填充TCA6416引脚状态到第9-10字节
|
// 填充TCA6416引脚状态到第9-10字节
|
||||||
tx[9] = tca6416_port0_status; // 第一个TCA6416的Port0状态
|
tx[9] = tca6416_port2_status; // 第二个TCA6416的Port0状态
|
||||||
tx[10] = tca6416_port1_status; // 第一个TCA6416的Port1状态
|
tx[10] = tca6416_port3_status; // 第二个TCA6416的Port1状态
|
||||||
tx[11] = tca6416_port2_status; // 第二个TCA6416的Port0状态
|
|
||||||
tx[12] = tca6416_port3_status; // 第二个TCA6416的Port1状态
|
|
||||||
|
|
||||||
// 填充AD7124原始数据到tx[13]~tx[77],每通道4字节,MSB格式
|
// 填充AD7124原始数据到tx[11]~tx[75],每通道4字节,MSB格式
|
||||||
extern ad7124_analog_t ad7124_analog[AD7124_CHANNEL_EN_MAX];
|
extern ad7124_analog_t ad7124_analog[AD7124_CHANNEL_EN_MAX];
|
||||||
for (int ch = 0; ch < AD7124_CHANNEL_EN_MAX; ++ch) {
|
for (int ch = 0; ch < AD7124_CHANNEL_EN_MAX; ++ch) {
|
||||||
int32_t data = ad7124_analog[ch].data;
|
int32_t data = ad7124_analog[ch].data;
|
||||||
tx[13 + ch * 4 + 0] = (data >> 24) & 0xFF;
|
tx[11 + ch * 4 + 0] = (data >> 24) & 0xFF;
|
||||||
tx[13 + ch * 4 + 1] = (data >> 16) & 0xFF;
|
tx[11 + ch * 4 + 1] = (data >> 16) & 0xFF;
|
||||||
tx[13 + ch * 4 + 2] = (data >> 8) & 0xFF;
|
tx[11 + ch * 4 + 2] = (data >> 8) & 0xFF;
|
||||||
tx[13 + ch * 4 + 3] = (data) & 0xFF;
|
tx[11 + ch * 4 + 3] = (data) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其余tx[77]~tx[83]可按需要填充(如比例阀等),此处保持原样或补零
|
// 其余tx[75]~tx[81]可按需要填充(如比例阀等),此处保持原样或补零
|
||||||
for (int i = 13 + AD7124_CHANNEL_EN_MAX * 4; i < 83; ++i) {
|
for (int i = 11 + AD7124_CHANNEL_EN_MAX * 4; i < 81; ++i) {
|
||||||
tx[i] = 0;
|
tx[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验和
|
// 校验和
|
||||||
uint16_t checksum = 0;
|
uint16_t checksum = 0;
|
||||||
for (int i = 4; i < 84; ++i) // 4~83(源地址+目标地址+类型+74字节)
|
for (int i = 4; i < 82; ++i) // 4~81(源地址+目标地址+类型+72字节)
|
||||||
{
|
{
|
||||||
checksum += tx[i];
|
checksum += tx[i];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue