多摩川编码器(Tamagawa Seiki)单圈/多圈/全信息协议
·
本文整理了基于 N32L40x MCU 的单圈绝对值、多圈计数、全信息及编码器ID协议的示例实现。请求应答时间均在 3µs 以内。
1. 协议帧示例
| 命令 | 名称 | 返回示例 | 帧长度 |
|---|---|---|---|
0x02 |
单圈绝对值 | 02 00 45 23 01 CRC |
6 字节 |
0x8A |
多圈计数 | 8A 00 00 00 00 CRC |
6 字节 |
0x1A |
全信息 | 1A 00 45 23 01 5A 00 00 00 00 CRC |
11 字节 |
0x92 |
编码器 ID | 92 00 5A CRC |
4 字节 |
注:
CRC 使用异或校验 (
Tamagawa_CRC8)
ENID(编码器ID)存储在tamagawa_data[4]单圈峰值
0x7FFFFF,到达后下一个值归零
2. 数据结构
// 内部数据数组(9字节)
uint8_t tamagawa_data[9];
// 数据含义
// [0] SF(状态标志)
// [1~3] 单圈值 ABS(23位)
// [4] 编码器ID
// [5~7] 多圈值 ABM(24位)
// [8] 报警标志
预建帧
uint8_t single_resp[SIG_FRAME_LEN]; // 单圈帧 6字节
uint8_t multi_resp[SIG_FRAME_LEN]; // 多圈帧 6字节
uint8_t allinfo_resp[FULL_FRAME_LEN]; // 全信息帧 11字节
uint8_t id_resp[ID_FRAME_LEN]; // 编码器ID帧 4字节
3. 核心函数
CRC 校验
uint8_t Tamagawa_CRC8(uint8_t *data, uint8_t len)
{
uint8_t xor = 0x00;
for (uint8_t i = 0; i < len; i++)
xor ^= data[i];
return xor;
}
更新数据并重建帧
void Tamagawa_Update_Data(uint32_t abs_position,
uint16_t enid,
uint32_t multi_turn,
uint8_t alarm)
{
abs_position &= 0x7FFFFF; // 23位单圈
multi_turn &= 0x00FFFFFF; // 24位多圈
tamagawa_data[1] = (uint8_t)(abs_position);
tamagawa_data[2] = (uint8_t)(abs_position >> 8);
tamagawa_data[3] = (uint8_t)(abs_position >> 16);
tamagawa_data[4] = (uint8_t)(enid & 0xFF);
tamagawa_data[5] = (uint8_t)(multi_turn);
tamagawa_data[6] = (uint8_t)(multi_turn >> 8);
tamagawa_data[7] = (uint8_t)(multi_turn >> 16);
tamagawa_data[8] = alarm;
BuildAllFrames(); // 重建所有应答帧
}
单圈递增(峰值归零)
void Tamagawa_IncreaseSingleTurn(void)
{
uint32_t cur = (uint32_t)(tamagawa_data[1])
| ((uint32_t)(tamagawa_data[2]) << 8)
| ((uint32_t)(tamagawa_data[3]) << 16);
if (cur >= SINGLE_TURN_PEAK) cur = 0;
else cur++;
tamagawa_data[1] = (uint8_t)(cur);
tamagawa_data[2] = (uint8_t)(cur >> 8);
tamagawa_data[3] = (uint8_t)(cur >> 16);
// 更新单圈帧
single_resp[1] = tamagawa_data[0];
single_resp[2] = tamagawa_data[1];
single_resp[3] = tamagawa_data[2];
single_resp[4] = tamagawa_data[3];
single_resp[5] = Tamagawa_CRC8(single_resp, 5);
// 同步全信息帧的单圈部分
allinfo_resp[1] = tamagawa_data[0];
allinfo_resp[2] = tamagawa_data[1];
allinfo_resp[3] = tamagawa_data[2];
allinfo_resp[4] = tamagawa_data[3];
allinfo_resp[10] = Tamagawa_CRC8(allinfo_resp, 10);
}
4. UART + DMA + RS485
-
GPIO PB6 控制 RS485 收/发
-
UART5 波特率 2.5Mbps,8N1
-
使用 DMA 加速发送,减少 CPU 占用
中断处理
void UART5_IRQHandler(void)
{
uint8_t cmd = UART5->DAT;
if(rs485_dma_tx_busy) return;
if(cmd == SINGLE_TURN_CMD)
Tamagawa_IncreaseSingleTurn();
uint8_t *buf;
uint16_t len;
switch(cmd) {
case SINGLE_TURN_CMD: buf = single_resp; len = SIG_FRAME_LEN; break;
case MULTI_TURN_CMD: buf = multi_resp; len = SIG_FRAME_LEN; break;
case ALL_INFO_CMD: buf = allinfo_resp;len = FULL_FRAME_LEN; break;
case ID_CMD: buf = id_resp; len = ID_FRAME_LEN; break;
default: return;
}
rs485_dma_tx_busy = 1;
RS485_ENABLE_TX();
USART_ConfigInt(UART5, USART_INT_RXDNE, DISABLE);
UART5_TX_DMA_CH->MADDR = (uint32_t)buf;
UART5_TX_DMA_CH->TXNUM = len;
DMA_ClearFlag(UART5_TX_DMA_CLEAR_FLAGS, DMA);
USART_ClrFlag(UART5, USART_FLAG_TXC);
USART_EnableDMA(UART5, USART_DMAREQ_TX, ENABLE);
DMA_EnableChannel(UART5_TX_DMA_CH, ENABLE);
}
5. 使用示例
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
DMA_Configuration();
Tamagawa_Update_Data(0x12345, 0, 0, 0);
NVIC_Configuration();
RS485_ENABLE_RX();
while(1) { } // 主循环
}
6. 总结
-
支持 单圈 / 多圈 / 全信息 / 编码器ID 四类命令
-
单圈命令自动递增,峰值归零
-
DMA + 中断方式保证高速响应 (<3µs)
-
RS485 半双工控制,硬件自动完成发送
更多推荐


所有评论(0)