新闻中心

EEPW首页>嵌入式系统>设计应用> 基於DRAM的单片机通信软件程序

基於DRAM的单片机通信软件程序

作者: 时间:2012-10-24 来源:网络 收藏
基於雙口RAM的單片機通信,軟件程序:
#define _DPRAMCOMM_H#include reg52.h> // 引用标准库的头文件#include absacc.h>#define uchar unsigned char #define LP_STT_SEM XBYTE[0x0000] // 左端状态旗语#define LP_PRO_SEM XBYTE[0x0001] // 左端配置旗语#define RP_STT_SEM XBYTE[0x0002] // 右端状态旗语#define RP_PRO_SEM XBYTE[0x0003] // 右端配置旗语#define INTL_SEM XBYTE[0x0004] // 左中断旗语#define INTR_SEM XBYTE[0x0005] // 右中断旗语#define DPRAM_INTL XBYTE[0x2FFF] // 右端口中断#define DPRAM_INTR XBYTE[0x2FFE] // 左端口中断#define READY 11 // 0x11表示准备就绪bit get_sem(uchar *sem_type);void InitProvRP(void);void Prov(void);void FillState(void);void GetState(void);uchar int0flag; // 外部中断0标志uchar rdyflag; // 另一端准备好标志uchar ProvTimes; // 表示配置次数uchar xdata *LpStateRamAddr; // 双口RAM左端状态空间起始地址uchar xdata *LpProvRamAddr; // 双口RAM左端配置空间起始地址uchar xdata *RpStateRamAddr; // 双口RAM右端状态空间起始地址 uchar xdata *RpProvRamAddr; // 双口RAM右端配置空间起始地址uchar xdata ArrayState[254]; // 存放状态信息的数组/* 40ms定时中断服务子程序:定期更新左端的状态信息,查询右端的状态信息*/void timer0_int() interrupt 1 using 1{TR0 = 0; // 关闭T0TH0 = 0x70; // 重置40ms定时器的计数初值TL0 = 0x00; FillState(); // 定期更新左端状态让右端单片机可查询GetState(); // 定期查询右端单片机的状态信息 } /* 外部中断0服务子程序:设置中断标志位int0flag,读清中断*/void out_int0() interrupt 0 using 1{uchar ch;int0flag = 1; // 表示外部中断0,实际是双口RAM产生的中断get_sem(INTL_SEM); // 申请并获得左中断旗语ch = DPRAM_INTR; // 读清中断INTL_SEM = 0x01; // 释放左中断旗语} /* 主程序 */void main(){ int0flag = 0;rdyflag = 0;ProvTimes = 0;LpStateRamAddr = 0x2000;LpProvRamAddr = 0x2400;RpStateRamAddr = 0x3000;RpProvRamAddr = 0x3400;/* 等待右端单片机准备就绪 */while(rdyflag!=1){get_sem(RP_STT_SEM); // 申请并获得右端状态旗语if (*RpStateRamAddr == READY) rdyflag = 1; // 右端单片机准备就绪标志置1RP_STT_SEM = 0x01; // 释放右端状态旗语}/* 对右端单片机进行初始配置 */InitProvRP(); /* 通过向左端状态空间的第一地址单元写READY向右端表示左端准备就绪 */get_sem(LP_STT_SEM); // 申请并获得左端状态旗语*LpStateRamAddr = READY; // 左端单片机准备就绪LP_STT_SEM = 0x01; // 释放左端状态旗语ProvTimes++; // 对右端口的配置次数加1 EA = 1; // 开CPU中断EX0 = 1; // 开外部中断0 ET0 =1; // 开T/C0中断PX0 = 0; // 外部中断低优先级PT0 = 1; // 计数器高优先级TMOD = 0x01; // T/C0工作在方式1TH0 = 0x70; // 预置40ms定时器的计数初值TL0 = 0x00;TR0 = 0; // 不启动T0/* 右端单片机接收左端对其的初始化配置,运行正常后触发双口RAM的左端中断,左端单片机受中断触发后对右端单片机作第二次配置,并启动40ms定时器,开始定期更新本机的状态信息并监测右端单片机的状态 */while(int0flag==1){if (ProvTimes==1){ProvTimes++; // 对右端口的配置次数加1Prov(); // 对右端口单片机二次配置/* 通过出发右端中断,通知右端单片机接受二次配置*/get_sem(INTR_SEM); // 申请并获得右中断旗语DPRAM_INTL = 0xFF; // ITNR脚为低,出发右端单片机中断INTR_SEM = 0x01; // 释放右中断旗语}TR0 = 1; // 启动40ms定时器T0 } }/* 申请并获得旗语函数 */bit get_sem(uchar *sem_type) {*sem_type = 0x00; // 申请旗语while((*sem_type!=0x00)); // 无限循环直至获得旗语 return(1);}/* 对右端单片机的初始化配置函数:为简化起见,通过向左端的配置空间2500H~25FFH全写0x22,表示对右端单片机的初始配置命令 */void InitProvRP(void){uchar i;get_sem(LP_PRO_SEM); // 申请左端配置旗语 for (i=0;i++;i=255)*(LpProvRamAddr+i) = 0x22; LP_PRO_SEM = 0x01; // 释放左端配置旗语 }/* 对右端单片机的二次配置函数:为简化起见,通过向左端的配置空间2500H~25FFH全写0x33,表示对右端单片机的初始配置命令 */void Prov(void){uchar i;get_sem(LP_PRO_SEM); // 申请左端配置旗语 for (i=0;i++;i=255)*(LpProvRamAddr+i) = 0x33; LP_PRO_SEM = 0x01; // 释放左端配置旗语}/* 更新本机状态函数:为了简化起见,此函数表示为向左端状态空间第一地址单元(存放设备就绪信息)以后的254字节全写0x44 */void FillState(void){uchar i;get_sem(LP_STT_SEM); // 申请并获得左端状态旗语for (i=0;i++;i=254)*(LpStateRamAddr+i+1) = 0x44;LP_STT_SEM = 0x01; // 释放左端状态旗语}/* 查询另一端单片机状态函数:为简化起见,此函数表示为用数组ArrayState存取右端状态空间第一地址单元(存放设备就绪信息)以后的254字节(3001H~30FFH)包含的状态信息 */ void GetState(void){uchar i;get_sem(RP_STT_SEM); // 申请并获得右端状态旗语for (i=0;i++;i=254)ArrayState[i] = *(RpStateRamAddr+i+1);RP_STT_SEM = 0x01; // 释放右端状态旗语}


评论


相关推荐

技术专区

关闭