博主用的是一款内嵌BU61580芯片的ARM9芯片,限于某些原因就不说芯片型号了。
该控制芯片将BU61580的寄存器和存储器区域映射到了这四个地址
#define BM1553b0MEM 0x81100000
#define BM1553b0REG 0x81104000
#define BM1553b1MEM 0x81000000
#define BM1553b1REG 0x81004000
该控制芯片包含两个1553控制器,下面将通过一个BC一个RT来实现回环通信。
1、BC端设置
*(volatile INT32U *)(BM1553b1REG + (3 << 2)) = 0x0001; //reset
*(volatile INT32U *)(BM1553b1REG + (7 << 2)) = 0x8000; //配置寄存器3#, bit15-设置增强模式
*(volatile INT32U *)(BM1553b1REG + (7 << 2)) = 0x8000; //配置寄存器3#,设置其他位
*(volatile INT32U *)(BM1553b1REG + (0 << 2)) = 0x0000; //EOM interupt
*(volatile INT32U *)(BM1553b1REG + (1 << 2)) = 0x0170; //配置寄存器1#,bit8-Frame Auto Repeat,bit6-Internal Trigger Enabled,bit5-Internal Message Gap Timer Enabled
//bit5-Internal Message Gap Timer Enabled,bit4-Retry Enabled
*(volatile INT32U *)(BM1553b1REG + (2 << 2)) = 0x1410; //配置寄存器2#
*(volatile INT32U *)(BM1553b1REG + (8 << 2)) = 0x11E0; //配置寄存器4#bit12-Expanded BC Control WORD,bit8-First Retry/Second Retry Alt,
*(volatile INT32U *)(BM1553b1REG + (9 << 2)) = 0x0800; //配置寄存器5#bit11-扩展过零点检测
*(volatile INT32U *)(BM1553b1REG + (13 << 2)) = 0x2710; //BC帧时间1s,分辨率100us
首先是设置BC端的寄存器,将上述1553B1作为BC端。这部分寄存器设置具体说明可以参考61580手册,这里不再赘述。
int i;
for(i=0;i<4096;i++)
{
*(volatile INT32U *)(BM1553b1MEM + (i << 2)) = 0x0; //初始化存储器
}
然后初始化1553B1的存储器区域
int i,j;
/消息块总配置——数量,指针
*(volatile INT32U *)(BM1553b1MEM + (0x100 << 2)) = 0x0; //set send stack pointer
*(volatile INT32U *)(BM1553b1MEM + (0x101 << 2)) = 0xfffb; //set messages in a frame (0xffff - value) 这里是四个消息块 0-3 如果只有一个消息 就设置0XFFFE
*(volatile INT32U *)(BM1553b1MEM + (0x102 << 2)) = 0x0; //set send stack pointer
*(volatile INT32U *)(BM1553b1MEM + (0x103 << 2)) = 0xfffb; //set messages in a frame (0xffff - value)
/消息块0
*(volatile INT32U *)(BM1553b1MEM + (0 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (1 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (2 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (3 << 2)) = 0x0108;//0x0108 信息块0的起始地址
//消息块存储区域范围:108-12D 总长度37 前面俩地址(108 109)放控制字和命令字 第三个地址(10A)开始放数据
*(volatile INT32U *)(BM1553b1MEM + (0x0108 << 2)) = 0x0100;
//0X0100->0001 0000 0000 0x0180->0001 1000 0000
//BC控制字 BIT8=1出错时允许重发,BIT7=1选择A通道/BIT7=0选择B通道,BIT=1本消息结束后产生中断
//BC控制字 0x0180 BIT8=1 使能重发 BIT7=1 选择A通道
//BC控制字 0x0100 BIT8=1 使能重发 BIT7=0 选择B通道
//BIT2-BIT0:000-BC-RT(T/_R和命令字第9位关联,1=RT-BC,0=BC-RT),010-BROADCAST,100-MODECODE,
*(volatile INT32U *)(BM1553b1MEM + (0x0109 << 2)) = 0x083E;
//命令字BIT0-4:RT ADD,BIT5:T/_R,BIT6-10:子地址;BIT11-15;数据个数,00000代表32/00001代表1
//PS:这个位置好像说反了,字节排序,RT地址按正常排序应该是11-15BIT
//BC命令字 0x083E 0000 1000 0011 1110 00001:RT1 0:接收 00001:子地址1 11110 :长度30bytes
//这个数据块是RT<-BC的方向,第10bit为0,代表BC要求RT接收数据。
for(i=0;i<30;i++)
{
*(volatile INT32U *)(BM1553b1MEM + ((0x010a + i) << 2)) = i; //放数据
}
/消息块1
*(volatile INT32U *)(BM1553b1MEM + (4 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (5 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (6 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (7 << 2)) = 0x012e;//0x012e 信息块1的起始地址
*(volatile INT32U *)(BM1553b1MEM + (0x012e << 2)) = 0x0180; //消息块的第一个地址放控制字,第二个放命令字
//控制字 BIT8=1出错时允许重发,BIT7=1选择A通道/BIT7=0选择B通道,BIT=1本消息结束后产生中断
//BC控制字 0x0100 BIT8=1 使能重发 BIT7=0 选择B通道 //BIT2-BIT0:000-BC-RT(T/_R和命令字第9位关联,1=RT-BC,0=BC-RT),010-BROADCAST,100-MODECODE,
*(volatile INT32U *)(BM1553b1MEM + (0x012f << 2)) = 0x083E;
//命令字BIT0-4:RT ADD,BIT5:T/_R,BIT6-10:子地址;BIT11-15;数据个数,00000代表32/00001代表1
//PS:这个位置好像说反了,字节排序,RT地址按正常排序应该是11-15BIT
//BC命令字 0x083E
//0000 1000 0011 1110
//00001:RT1
//0:接收
//00001:子地址1
//11110:长度30bytes
//这个数据块是RT<-BC的方向,第10bit为0,代表BC要求RT接收数据。
for(i=0;i<30;i++)
{
*(volatile INT32U *)(BM1553b1MEM + ((0x130 + i) << 2)) = i; //数据
}
/消息块2
*(volatile INT32U *)(BM1553b1MEM + (8 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (9 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (10 << 2)) = 0x0;//消息间隔4.096ms
*(volatile INT32U *)(BM1553b1MEM + (11 << 2)) = 0x0154;//0x0154 信息块2的起始地址
*(volatile INT32U *)(BM1553b1MEM + (0x0154 << 2)) = 0x0104; //控制字 BIT8=1出错时允许重发,BIT7=1选择A通道/BIT7=0选择B通道,BIT=1本消息结束后产生中断
//BC控制字 0x0184 BIT8=1 使能重发 BIT7=1 选择A通道 BIT2=1 模式码
//BIT2-BIT0:000-BC-RT(T/_R和命令字第9位关联,1=RT-BC,0=BC-RT),010-BROADCAST,100-MODECODE,
*(volatile INT32U *)(BM1553b1MEM + (0x0155 << 2)) = 0x0C10;
//命令字BIT0-4:RT ADD,BIT5:T/_R,BIT6-10:子地址;BIT11-15;数据个数,00000代表32/00001代表1
//命令字0x0c10:0000 1100 0001 0000
//00001 :RT1
//1:T
//00000:方式码
//10000:发送矢量字
//PS:这个位置好像说反了,字节排序,RT地址按正常排序应该是11-15BIT
//这个数据块是RT->BC的方向,第10bit为1,代表BC要求RT发送数据。
//读取数据就不需要往存储区域里写数据
/消息块3
*(volatile INT32U *)(BM1553b1MEM + (12 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (13 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (14 << 2)) = 0x0;
*(volatile INT32U *)(BM1553b1MEM + (15 << 2)) = 0x0180;//信息块3的起始地址
*(volatile INT32U *)(BM1553b1MEM + (0x0180 << 2)) = 0x0184; //控制字 BIT8=1出错时允许重发,BIT7=1选择A通道/BIT7=0选择B通道,BIT=1本消息结束后产生中断
//BC控制字 0x0104 BIT8=1 使能重发 BIT7=0 选择B通道 BIT2=1 模式码 //BIT2-BIT0:000-BC-RT(T/_R和命令字第9位关联,1=RT-BC,0=BC-RT),010-BROADCAST,100-MODECODE,
*(volatile INT32U *)(BM1553b1MEM + (0x0181 << 2)) = 0x0C10;
//命令字BIT0-4:RT ADD,BIT5:T/_R,BIT6-10:子地址;BIT11-15;数据个数,00000代表32/00001代表1
//PS:这个位置好像说反了,字节排序,RT地址按正常排序应该是11-15BIT
//命令字0x0c10:0000 1100 0001 0000 表示00001 :RT1 1:发送 00000:方式码 10000:发送矢量字
//这个数据块是RT->BC的方向,第10bit为1,代表BC要求RT发送数据。
//读取数据就不需要往存储区域里写数据
然后是关键的一个部分,在1553B1的存储器区域设置BC端需要实现的消息,这里写入了四条消息,分别实现两条BC=>RT,两条RT=>BC。细节均在代码里进行备注。
*(volatile INT32U *)(BM1553b1REG + (0x0 << 2)) = 0x0008; //EOM interupt 这个似乎是消息结束后中断
*(volatile INT32U *)(BM1553b1REG + (0x3 << 2)) = 0x0002; //Start Send
最后是打开EOM中断和开启BC,这里的EOM中断是BC消息帧结束中断。
2、BC中断服务
Nowpos = *(volatile INT32U *)(BM1553b0MEM + (0x100 << 2)) ; //堆栈指针
Nowpos = Nowpos & 0xfc;
for( ; Nowpos != Lastpos; Lastpos = ( Lastpos + 4) & 0xff ) //判定堆栈指针是否有移动
{
State_word = *(volatile INT32U *)(BM1553b0MEM + ((Lastpos ) << 2)); //读出状态字
Adr_data = *(volatile INT32U *)(BM1553b0MEM + ((Lastpos + 2) << 2)); //读出地址字
Com_word = *(volatile INT32U *)(BM1553b0MEM + ((Lastpos + 3) << 2)); //读出命令字
Sub_adr = Com_word & 0x07e0; //解析出子地址
Channel_A_B = State_word & 0x2000; //解析出通道来源
//printf("A_B %x\r\n",State_word);
printf("A_B %d\r\n",(Channel_A_B>>13)); //状态字第十三位是AB通道标志
if(Sub_adr == 0x20)//接收消息 //判定接收消息的子地址来源
{
for(i=0;i<30;i++)
{
R1553B_DATA[i] = *(volatile INT32U *)(BM1553b0MEM + ((0x420+i)<< 2));//接收到的数据
}
for(i=0;i<30;i++)
{
*(volatile INT32U *)(BM1553b0MEM + ((0x820+i)<< 2))=T1553B_DATA[i];//需要发送的数据 写到RT0里 实际上是完成一个回环测试?
}
*(volatile INT32U *)(BM1553b0MEM + (0x120 << 2)) = 0x0001; //置矢量字 这个是RT0的东西 在手册里暂时没找到说明
}
else if(Sub_adr == 0x420)//发送消息 子地址有这么多吗?不是就0-32么
{
*(volatile INT32U *)(BM1553b0MEM + (0x120 << 2)) = 0x0000; //清矢量字,矢量字存储在地址0x120
}
}
这里需要说明的是,本控制芯片将61580芯片内嵌,所以使用专门的中断标志位即可实现中断,如果是外部的61580则需要使用外部输入中断来识别芯片提供的中断信号。
这部分中断服务程序,是从别的地方搞到的,所以有些地方还没有理解清楚。
暂时更新到这里,后面会着重去理解终端服务程序里标注问号的位置。