求熟悉Silicon的c8051f系列单片机进来看看,解决XBYTE读取XRAM数据问题手机费酬谢
[复制链接]
求大神指导,解决了手机费100酬谢,使用c8051f505,datasheet链接贴出:https://www.silabs.com/documents/public/data-sheets/C8051F50x-51x.pdf,总体思路就是复用地址数据总线,在定时器1中读取FPGA地址过来的数据,程序初始化完成后就等着8位计数中断,中断函数读取地址中的数据,别人用汇编写好的程序能够正常运行,我翻译成c之后进入中断读取不XBYTE[0X2001];数据。源码贴出:汇编代码:
cseg AT 00H
LJMP MAIN
ORG 000BH
LJMP A1CDF
ORG 001BH
LJMP A1CC8
MAIN:
ANL PCA0MD, #0BFh
MOV SFRPAGE, #CONFIG_PAGE
MOV OSCICN, #0C5H
MOV P0SKIP, #03H
MOV P1SKIP , #0E0H
MOV XBR0, #00H ;交叉开关使能
MOV XBR1, #0C0H
MOV XBR2, #040H
;MOV XBR3, #00H
MOV P2MDIN, #0FH ;端口配置,P0开漏,p1,P4口为推挽输出
MOV P1MDOUT, #0E7H
MOV P2MDOUT, #0FH
MOV P3MDOUT, #0FFH ;P0-p4端口为数字输入,p2四位模拟输入端口
MOV P4MDOUT, #0FFH
MOV EMI0CF, #09H
MOV EMI0TC, #045H
MOV SFRPAGE,#ACTIVE_PAGE
LCALL A1D30
CLR P1.4 ;开接收
SETB EA ;清中断屏蔽位,开CPU中断
A1875: MOV B,#00H
SETB P1.0
CLR P1.0
MOV B,#00H
A1885: ;等待T1中断接收数据,主函数,
NOP
NOP
NOP
NOP
JNB B.3,A1885 ;通过BB3判断接收是否完成.
MOV A,COM_DATA
JNZ A1893 ;Is it command ?
MOV B,#00H
LJMP A1885 ;是数据,继续等待接收!
A1CC8: PUSH DPL ;接收中断服务子程(T1中断)
PUSH DPH
PUSH ACC
MOV DPTR,#2001H
MOVX A,@DPTR
JB B.0,A1D19
MOV RMSB,A
MOV COM_DATA,#00H
;SETB P2.1
JNB P1.3,A1D1D
MOV COM_DATA,#0FFH
A1D1D: SETB B.0
SJMP LP5
A1D19: MOV RLSB,A
SETB B.3
SJMP LP5
A1D30: ;定义定时器子程
SETB TR1
SETB ET1
SETB TR0
SETB ET0
MOV TMOD,#66H
MOV TH0,#0F8H
MOV TL0,#0F8H
MOV TH1,#0F8H
MOV TL1,#0F8H
RET
END
翻译后c代码:
#include <compiler_defs.h>
#include <C8051F500_defs.h> // SFR declarations
#include <absacc.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//#define XBYTE ((unsigned char volatile SEG_XDATA *) 1000)
uchar xdata *pchar;
uchar BB0,BB3,BB4,test;
sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;
sbit P14=P1^4;
sbit P15=P1^5;
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
void Oscillator_Init(void);
void EMI_IN(void);
void Port_IO_Init(void);
void Timer_Init(void) ;
void CCAR_COMM(uchar m) ;
INTERRUPT_PROTO (TIMER1_ISR, INTERRUPT_TIMER1);
void main(void)
{
SFRPAGE = ACTIVE_PAGE; // Set SFR Page for PCA0MD
PCA0MD &= 0xBF; // Disable Watchdog timer
PCA0MD=0x00;
Oscillator_Init();
Port_IO_Init();
EMI_IN();
// XBYTE[0X2001]=0X30;
// P11=0;
BB0=0;
BB3=0;
BB4=0;
Timer_Init() ;
P10=1;
P14=0; //开接收
EA=1; //开中断
while(1)
{
BB0=0;
BB3=0;
BB4=0;
P10=1;
Delay_us(20); //A1DF0;
P10=0;
BB0=0;
BB3=0;
BB4=0;
//RLSB=XBYTE[0X2001];
while(!BB3);
if(COM_DATA) //判断是数据还是命令
CCAR_COMM(RMSB);
}
}
void Oscillator_Init(void)
{
//SFRPAGE_SAVE=SFRPAGE;
SFRPAGE = CONFIG_PAGE;
OSCICN = 0xC5;
SFRPAGE = ACTIVE_PAGE;
}
//定时器初始化//A1D30
void EMI_IN(void)
{
//SFRPAGE_SAVE = SFRPAGE;
SFRPAG=CONFIG_PAGE;
EMI0CF = 0x09; //配置EMIF端口复用方式,带块选择的分片方式,<4k用内存,>4k用外存
EMI0TC = 0x45; //最小地址建立时间、最大保持时间。原值55H
SFRPAGE=ACTIVE_PAGE ;
//SFRPAGE = SFRPAGE_SAVE;
}
void Port_IO_Init(void)
{
//SFRPAGE_SAVE = SFRPAGE;
SFRPAGE = CONFIG_PAGE;
P0SKIP = 0x03; // Skip P0.0 and P0.1
P1SKIP = 0xE0;
XBR0 = 0x00;
XBR1 = 0xC0; //T2、T1、T0连接到端口引脚
XBR2 = 0x40; //使能交叉开关
P2MDIN = 0x0F; //设置P2口没有模拟输入
P1MDOUT = 0xE7; //推挽输出带负载能力强
P2MDOUT = 0x0F;
P3MDOUT = 0xFF;
P4MDOUT = 0xFF;
SFRPAGE=ACTIVE_PAGE ;
//SFRPAGE = SFRPAGE_SAVE;
}
void Timer_Init(void)
{
// SFRPAGE = CONFIG_PAGE;
// TCON=0x00;
// EA=1;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
TMOD=0x66;
TL0=0xF8;
TH0=0xF8;
TL1=0xF8;
TH1=0xF8;
// SFRPAGE=ACTIVE_PAGE ;
}
//命令判断
void CCAR_COMM(uchar m)
{
switch(m)//A1893
{
case 0x20: //2000H命令(时间谱短节通讯检查)是双字命令
DOUBLE_REC(); //等待接收双命令字的第二个字,如果第二个是命令字则返回到最初的命令判断,如果是数据,则返回到原命令继续执行
P14=1; //关接收
SLSB=RLSB; //将接收数据放到发送数据存储地址。
SMSB=RMSB;
// Delay_bms(2);
// P04=!P04;
S_GUIDE(SMSB);
while(!BB4);
// Delay_us(600);
P14=0;
break;
default:
C_ERR=0x08;
break;
}
}
//接收中断 //接收数据 (实际函数初始化完毕后就等T1中断接收数据)
INTERRUPT(Timer1_ISR, INTERRUPT_TIMER1)
//void Timer1_ISR(void) interrupt 3
{
pchar=2001+1000;
if(BB0)
{
RLSB=XBYTE[0X2001];
BB3=1;
}
else
{
RMSB=XBYTE[0X2001];
// RMSB=*pchar;
COM_DATA=0x00;
if(P13==0)BB0=1;
else
{
COM_DATA=0xff;
BB0=1;
}
}
}
|