赞
踩
HI-3593是一款ARINC429协议收发器芯片,和之前介绍的HI-3582芯片功能一样,该芯片支持两路接收和一路发送,其中每个接收机具有标签识别、32×32 FIFO和模拟线路接收机。不同的是HI-3593通信接口为SPI总线,可以减少MCU的硬件管脚负担,而且HI-3593片内集成DC/DC 转换器用于产生双极性ARINC 429差分电压以便直接驱动ARINC 429总线,就不用像HI-3582那样需要提供±10V信号,这样使电路设计更加简洁。
HI-3593硬件设计十分方便,电源方面只需要提供3.3V供电,外部提供1MHz的时钟信号。如果你像我一样不使用标签过滤器的话,除了SPI总线以外,MCU只需要使用RxINT、RxFLAG、TFULL这几个状态管脚即可。参考设计如下图:
HI-3593通过SPI总线通信,使用的是SPI模式0,最高支持10MHz通信速率,对于ARINC429的通信速率来说已经绰绰有余了。HI-3593主要的寄存器有接收控制寄存器(0x10,0x24)、发送控制寄存器(0x08)、ACLK分频寄存器(0x38)和标志中断寄存器(0x34),基本上初始化这几个寄存器就可以正常通信了。
接收控制寄存器
根据以上寄存器位的描述,很多时候需要翻转接收到的429消息的LABEL,这时RFLIP就要置1。我们不需要过滤SD9/10信息,所以SDON设置为0。PARITY为1,使能奇偶校验。LABREC、PLON为0,不使能标签过滤。RATE为0,设置为429通信速率为高速,也就是100kbps。
发送控制寄存器
TFLIP和上面接收翻转功能一样,置1后发送时翻转Label数据。TMODE置1,只要数据有效就发送出去。SELFTEST是自测试位,置1后会内部收发自环。PARITY和RATE同上。
ACLK分频寄存器
这里使用的是1MHz外部晶振,所以DIV设置位0x00
标志中断寄存器
可以通过RxFLAG和RxINT管脚来判断是否接收到有效数据。RxFLAG设置为0,这样FIFO内接收到有效数据后管脚会变高,当数据被完全读取后管脚又被拉低。RxINT同样设置为0,当接收到有效数据会产生一个高脉冲中断信号。RxFLAG管脚适合用轮询的方法判断FIFO是否有数据,RxINT适用于中断的方式接收数据。由于ARINC429速率并不高,所以本文采用的是轮询方式接收数据,通过查询RxFLAG管脚是否为高,来判断FIFO内是否接收到有效数据。
本例程是结合上面寄存器配置,通过轮询的方式接收数据,寄存器初始化时采用了结构体位域的方式进行配置,这样更加方便直观的设置每一位寄存器。通信过程中发现了一个问题,就是我发送的数据和接收端接收到的数据正好高低位翻转了,现在还没找到具体原因,只能通过函数dataFlip先翻转了数据然后再发送,有知道具体原因的朋友可以留言告诉我一下。
#include "ARINC429.h" #include "Hal.h" #define ARINC_SELF_TEST 0 /*管脚定义*/ #define ARINC_TFULL_PIN 0x42 #define ARINC_TEMPTY_PIN 0x43 #define ARINC_R1FLAG_PIN 0x44 #define ARINC_R1INT_PIN 0x45 #define ARINC_R2FLAG_PIN 0x46 #define ARINC_R2INT_PIN 0x22 #define ARINC_RESET_PIN 0x47 /*Regs定义*/ #define ARINC_SEND_CTRL_WREG 0x08 #define ARINC_SEND_CTRL_RREG 0x84 #define ARINC_FIFO_DATA_REG 0x0C #define ARINC_RECV1_CTRL_WREG 0x10 #define ARINC_RECV1_CTRL_RREG 0x94 #define ARINC_RECV2_CTRL_WREG 0x24 #define ARINC_RECV2_CTRL_RREG 0xB4 #define ARINC_INT_FLAG_WREG 0x34 #define ARINC_INT_FLAG_RREG 0xD0 #define ARINC_ACLK_DIV_WREG 0x38 #define ARINC_ACLK_DIV_RREG 0xD4 #define ARINC_FIFO_SEND_REG 0x40 #define ARINC_RECV1_FIFO_REG 0xA0 #define ARINC_RECV2_FIFO_REG 0xC0 #define ARINC_DATA_VALID(ch) (HalGPIOGetLevel(ARINC_R##ch##FLAG_PIN) == 0) /*寄存器结构体*/ #pragma pack(1) typedef struct { int RATE : 1; int PLON : 1; int LABREC: 1; int PARITY: 1; int SDON : 1; int SD10 : 1; int SD9 : 1; int RFLIP : 1; }ARINCRecvCtrlReg_t; typedef struct { int RATE : 1; int X : 1; int TPARITY : 1; int ODDEVEN : 1; int SELFTEST: 1; int TMODE : 1; int TFLIP : 1; int HIZ : 1; }ARINCSendCtrlReg_t; typedef struct { int X2 :1; int DIV :4; int X1 :3; }ARINCAclkDivReg_t; typedef struct { int R1FLAG :2; int R1INT :2; int R2FLAG :2; int R2INT :2; }ARINCINTReg_t; typedef struct { int label : 8; int sdi : 2; int data : 19; int ssm : 2; int parity : 1; } ARINC429Data_t; #pragma pack() typedef union { uint8_t val; ARINCRecvCtrlReg_t recvCtrl; ARINCSendCtrlReg_t sendCtrl; ARINCAclkDivReg_t aclkDiv; ARINCINTReg_t intFlag; }ARINCReg_t; typedef union { uint32_t db; ARINC429Data_t ex; } ARINCdataFlip_t; static ARINC429DataRecv_cb g_recvCallback = NULL; static uint32_t dataFlip(uint32_t data) //翻转高低字节 { uint32_t result = data; #if 1 result = (data >> 24); result |= (data >> 8) & 0xff00; result |= (data << 8) & 0xff0000; result |= (data << 24); #endif return result; } static void chipReset(void) //硬件复位 { HalGPIOSetLevel(ARINC_RESET_PIN, 1); HalWaitMs(1); HalGPIOSetLevel(ARINC_RESET_PIN, 0); //reset HalWaitMs(1); } static void regsConfig(void) //寄存器初始化函数 { ARINCReg_t reg; reg.recvCtrl.RFLIP = 1; //是否翻转前八位LABEL数据 reg.recvCtrl.SD9 = 0; reg.recvCtrl.SD10 = 0; reg.recvCtrl.SDON = 0; //是否匹配SD9\10两位,否 reg.recvCtrl.PARITY = 1; //接收字的奇偶性检查启用 reg.recvCtrl.LABREC = 0; //标签过滤关闭 reg.recvCtrl.PLON = 0; //优先级标签寄存器的不使能 reg.recvCtrl.RATE = 0; //高速数据传输速率 HalSPIWriteReg(ARINC_RECV1_CTRL_WREG, reg.val); HalSPIWriteReg(ARINC_RECV2_CTRL_WREG, reg.val); reg.sendCtrl.HIZ = 0; //设置该位使片内线路驱动器输出进入高阻态 reg.sendCtrl.TFLIP = 1; //是否翻转前八位LABEL数据 reg.sendCtrl.TMODE = 1; //只要数据是有效的就会被立即发送 reg.sendCtrl.SELFTEST = ARINC_SELF_TEST; //自测试 reg.sendCtrl.ODDEVEN = 0; //偶校验 reg.sendCtrl.TPARITY = 1; //使能校验位 reg.sendCtrl.X = 0; reg.sendCtrl.RATE = 0; //高速数据传输速率 HalSPIWriteReg(ARINC_SEND_CTRL_WREG, reg.val); reg.val = 0; reg.aclkDiv.DIV = 0; //1MHz HalSPIWriteReg(ARINC_ACLK_DIV_WREG, reg.val); reg.intFlag.R1FLAG = 0; //接收器1 FIFO为空时, R1FLAG变高 reg.intFlag.R1INT = 0; //当有效消息被接收,R1INT为高脉冲 reg.intFlag.R2FLAG = 0; reg.intFlag.R2INT = 0; HalSPIWriteReg(ARINC_INT_FLAG_WREG, reg.val); } static uint32_t readData(uint8_t chnl) //读通道数据 { uint8_t reg; uint32_t data; if(chnl == 1) { reg = ARINC_RECV1_FIFO_REG; } else { reg = ARINC_RECV2_FIFO_REG; } HalSPIRead(reg, (uint8_t *)&data, sizeof(uint32_t)); return dataFlip(data); } /*发送数据*/ void ARINC429Send(unsigned char label, unsigned int value, unsigned char ssm) { ARINCdataFlip_t data; uint32_t num; memset(&data, 0, sizeof(ARINCdataFlip_t)); data.ex.label = label; data.ex.data = value; data.ex.ssm = ssm; data.ex.sdi = 0; num = dataFlip(data.db); HalSPIWrite(ARINC_FIFO_DATA_REG, (uint8_t *)&num, sizeof(uint32_t)); } static void dataRecvHandle(void) { ARINCdataFlip_t data; if(ARINC_DATA_VALID(1)) //通过RxFLAG管脚判断是否接收到有效数据 { data.db = readData(1); //读通道1数据 if(g_recvCallback != NULL) { g_recvCallback(data.ex.label, data.ex.data, data.ex.ssm); } } if(ARINC_DATA_VALID(2)) { data.db = readData(2); if(g_recvCallback != NULL) { g_recvCallback(data.ex.label, data.ex.data, data.ex.ssm); } } } /*初始化*/ void ARINC429Init(ARINC429DataRecv_cb recvHandle) { chipReset(); regsConfig(); g_recvCallback = recvHandle; } void ARINC429Poll(void) { dataRecvHandle(); //轮询接收 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。