下面这段PCF8563读写程序不知道哪里出问题了,在proteus仿真时出现错误 Internal Exception:access violation in module 'PCF8563.DLL' ,请问是我程序问题还是软件问题
proteus可以仿真其他电路。谢谢了~
附程序:#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS = P2^5; /*LCD1602指令,数据控制端口*/
sbit LCD_RW = P2^6;/*LCD1602读、写控制端口*/
sbit LCD_EN = P2^7;/*LCD1602使能*/
sbit pcf8563_scl=P2^2;
sbit pcf8563_sda=P2^3;
bit flag=1,hour=0,min=0;
bit year=0,month=0,day=0,week=0;
bit busy=0;
uchar timecount=0,count=0;
uchar code mytab[8] = {0x01,0x1b,0x1d,0x19,0x1d,0x1b,0x01,0x00};/*小喇叭形状定义*/
uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uchar init2[] ={0x00,0x00,0x12,0x01,0x06,0x01,0x00};
/*秒,分, 时, 日, 月,星期,年,默认时间设置*/
void Set_place(uchar row,uchar col);
void Play_nowtime();
void start_pcf8563();
void stop_pcf8563();
void read();
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void delay1(int ms)/*延时*/
{
unsigned char y;
while(ms--)
{
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/*检查LCD忙状态,lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据*/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*写指令数据到LCD,RS=L,RW=L,E=高脉冲,D0-D7=指令码*/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*写显示数据到LCD,RS=H,RW=L,E=高脉冲,D0-D7=数据*/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/* LCD初始化设定 */
void init_lcd()
{
delay1(15);
lcd_wcmd(0x01); /*清除LCD的显示内容*/
lcd_wcmd(0x38); /*设置16×2显示,5×7点阵,8位数据接口*/
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x0c); /*显示开,关光标*/
delay1(5);
lcd_wcmd(0x06); /*移动光标*/
delay1(5);
lcd_wcmd(0x01); /*清除LCD的显示内容*/
delay1(5);
}
/* 设定显示位置*/
void write_position(uchar row,uchar col)
{
uchar place;
if(row==1)
{
place=0x80+col-1;
lcd_wcmd(place);
}
else
{
place=0xc0+col-1;
lcd_wcmd(place);
}
}
/*自定义字符写入CGRAM*/
void writetab()
{
unsigned char i;
lcd_wcmd(0x40); /*写CGRAM*/
for (i = 0; i< 8; i++)
lcd_wdat(mytab);
}
void Send_pcf8563_byte(uchar bb) /*向PCF8563发送一个字节*/
{
uchar aa;
pcf8563_scl=0;
for(aa=0;aa<8;aa++)
{
if((bb&0x80)==0x80)
{
pcf8563_sda=1;
}
else
{
pcf8563_sda=0;
}
pcf8563_scl=1;
pcf8563_scl=0;
bb=bb<<1;
}
_nop_();
_nop_();
pcf8563_sda=1;
pcf8563_scl=1;
busy=0;
if(pcf8563_sda)
{
busy=1;
}
else
{
_nop_();
_nop_();
pcf8563_scl=0;
busy=0;
}
}
receive_pcf8563_byte() /*从PCF8563接受一个字节*/
{
uchar CC;
uchar k;
k=0;
pcf8563_sda=1;
for(CC=0;CC<8;CC++)
{
k=(k<<1)|pcf8563_sda;
pcf8563_scl=0;
pcf8563_scl=1;
_nop_();
_nop_();
}
pcf8563_scl=0;
_nop_();
_nop_();
return k;
}
void write_pcf8563(uchar subadd,uchar dat)/* 向PCF8563对应地址写数据*/
{
start_pcf8563();
Send_pcf8563_byte(0xa2);
if(!busy)
{
Send_pcf8563_byte(subadd);
if(!busy)
{
Send_pcf8563_byte(dat);
}
}
stop_pcf8563();
}
void set_pcf8563(uchar addr,uchar *p,uchar n) /*写入n个数据*/
{
for(;n>=0;n--)
{
write_pcf8563(addr,*p);
p++;
addr=addr+1;
}
}
void read_pcf8563(void) /*读当时的时间,日期,月,星期,年*/
{
uchar i;
start_pcf8563();
Send_pcf8563_byte(0xa2);
if(!busy)
{
Send_pcf8563_byte(0x02);
if(!busy)
{
for(i=0;i<8;i++)
{
start_pcf8563();
Send_pcf8563_byte(0xa3);
init=receive_pcf8563_byte();
}
}
stop_pcf8563();
}
}
void start_pcf8563() /*开启PCF8563IIC*/
{
pcf8563_sda=1;
pcf8563_scl=1;
pcf8563_sda=0;/*SCL为低,SDA执行一个上跳*/
pcf8563_scl=0;/*SCL为低,嵌住数据线*/
}
void stop_pcf8563() /*关闭PCF8563IIC */
{
pcf8563_sda=0;
pcf8563_scl=1;
pcf8563_sda=1;/*SCL为高,SDA执行一个上跳 */
pcf8563_scl=0;/*SCL为低,嵌住数据线*/
}
/* 主函数*/
void main()
{
P1=0xff;
TMOD=0x01; /*定时器工作方式1,16位定时*/
TH0=0x4c; /*50ms定时*/
TL0=0x00;
EA=1;
ET0=1; /*允许定时器0中断*/
TR0=1;
init_lcd(); /*初始化LCD*/
writetab(); /*自定义字符写入CGRAM*/
set_pcf8563(0x02,init2,7); /*自动设置初始时间,日期,年月*/
read();
Play_nowtime();
}
/*Time0中断函数*/
void Time0(void) interrupt 1 using 0
{
TH0=0x4c; /*50ms定时*/
TL0=0x00;
timecount++;
if(timecount>9)
{
timecount=0;
flag=~flag;
}
}
/* 显示当前时间*/
void Play_nowtime()
{
write_position(2,1);
lcd_wdat(((init[2]&0xf0)>>4)+0x30);
write_position(2,2);
lcd_wdat('0'+(init[2]&0x0f)); /*读小时*/
write_position(2,4);
lcd_wdat('0'+((init[1]&0xf0)>>4));
write_position(2,5);
lcd_wdat('0'+(init[1]&0x0f)); /*读分钟*/
write_position(2,7);
lcd_wdat('0'+((init[0]&0xf0)>>4));
write_position(2,8);
lcd_wdat('0'+(init[0]&0x0f)); /*读秒*/
write_position(1,3);
lcd_wdat('0'+((init[6]&0xf0)>>4));
write_position(1,4);
lcd_wdat('0'+(init[6]&0x0f)); /*读年*/
write_position(1,1); /*写入年的第一位*/
lcd_wdat('2');
write_position(1,2); /*写入年的第二位*/
lcd_wdat('0');
write_position(1,6);
lcd_wdat('0'+((init[5]&0xf0)>>4));
write_position(1,7);
lcd_wdat('0'+(init[5]&0x0f)); /*读月*/
write_position(1,9);
lcd_wdat('0'+((init[3]&0xf0)>>4));
write_position(1,10);
lcd_wdat('0'+(init[3]&0x0f)); /*读日*/
write_position(1,16);
lcd_wdat('0'+(init[4]&0x07)); /*读星期*/
write_position(1,5);
lcd_wdat('/');
write_position(1,8); /*在年月之间加上符号"/" */
lcd_wdat('/');
write_position(1,11); /*在年月之间加上符号"/" */
lcd_wdat('/');
write_position(1,12); /*在年月之间加上符号"/" */
lcd_wdat('W');
write_position(1,13); /*在年月之间加上符号"/" */
lcd_wdat('e');
write_position(1,14); /*在年月之间加上符号"/" */
lcd_wdat('e');
write_position(1,15); /*在年月之间加上符号"/" */
lcd_wdat('k');
write_position(2,3);
lcd_wdat(':');
write_position(2,6); /*在时,分,秒之间加上符号":"*/
lcd_wdat(':');
}