
/* ME300B单片机开发系统演示程序 - 多花样流水灯
/* LED显示 */
/* 将演示数据先写入24C02芯片内,再将其数据逐个读出送P0口LED显示。
作者: gguoqing 时间: 2006/06/20
/*【版权】Copyright(C)伟纳电子 www.willar.com All Rights Reserved */
/*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!
/*******************************************************************/
#include #include #define uchar unsigned char #define uint unsigned int #define OP_WRITE 0xa0 // 器件地址以及写入操作 #define OP_READ 0xa1 // 器件地址以及读取操作 uchar code display[72]={ 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F, 0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF, 0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00, 0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF, 0xFC,0xF9,0xF3,0xE7,0xCF,0x9F,0x3F, 0x9F,0xCF,0xE7,0xF3,0xF9,0xFC,0xFF, 0xE7,0xDB,0xBD,0x7E,0xBD,0xDB,0xE7,0xFF, 0xE7,0xC3,0x81,0x00,0x81,0xC3,0xE7,0xFF, 0xAA,0x55,0x18,0xFF,0xF0,0x0F, 0x00,0xFF,0x00,0xFF }; sbit SDA = P3^4; sbit SCL = P3^3; void start(); void stop(); uchar shin(); bit shout(uchar write_data); void write_byte( uchar addr, uchar write_data); void fill_byte(uchar fill_size,uchar fill_data); void delayms(uint ms); uchar read_current(); uchar read_random(uchar random_addr); #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();}; /**********************************************************/ main(void) { uchar i; SDA = 1; SCL = 1; fill_byte(72,0xff); // 将前72字节填充0xff for(i = 0 ; i < 72; i++) //写入显示代码到AT24C02 { write_byte(i,display[i]); } for(i =0 ;i <72 ; i++) //从AT24C02移出数据送到P0口显示 { P0 = read_random(i); delayms(350); } } /**********************************************************/ void start() //开始位 { SDA = 1; SCL = 1; delayNOP(); SDA = 0; delayNOP(); SCL = 0; } /**********************************************************/ void stop() // 停止位 { SDA = 0; delayNOP(); SCL = 1; delayNOP(); SDA = 1; } /**********************************************************/ uchar shin() // 从AT24C02移出数据到MCU { uchar i,read_data; for(i = 0; i < 8; i++) { SCL = 1; read_data <<= 1; read_data |= SDA; SCL = 0; } return(read_data); } /********************************* *************************/ bit shout(uchar write_data) // 从MCU移出数据到AT24C02 { uchar i; bit ack_bit; for(i = 0; i < 8; i++) // 循环移入8个位 { SDA = (bit)(write_data & 0x80); _nop_(); SCL = 1; delayNOP(); SCL = 0; write_data <<= 1; } SDA = 1; // 读取应答 delayNOP(); SCL = 1; delayNOP(); ack_bit = SDA; SCL = 0; return ack_bit; // 返回AT24C02应答位 } /**********************************************************/ void write_byte(uchar addr, uchar write_data) // 在指定地址addr处写入数据write_data { start(); shout(OP_WRITE); shout(addr); shout(write_data); stop(); delayms(10); // 写入周期 } /**********************************************************/ void fill_byte(uchar fill_size,uchar fill_data) // 填充数据fill_data到EEPROM内fill_size字节 { uchar i; for(i = 0; i < fill_size; i++) { write_byte(i, fill_data); } } /**********************************************************/ uchar read_current() // 在当前地址读取 { uchar read_data; start(); shout(OP_READ); read_data = shin(); stop(); return read_data; } /**********************************************************/ uchar read_random(uchar random_addr) // 在指定地址读取 { start(); shout(OP_WRITE); shout(random_addr); return(read_current()); } /**********************************************************/ void delayms(uint ms) // 延时子程序 { uchar k; while(ms--) { for(k = 0; k < 120; k++); } } /**********************************************************/ SDA BIT P3.4 ;定义24C02数据线 SCL BIT P3.3 ;定义24C02时钟线 ;----------------------------------------------------- ORG 0000H AJMP MAIN ORG 0030H ;----------------------------------------------------- MAIN: MOV SP,#60H MOV P0,#0FFH ACALL WRITE_DATA M_LOOP: ACALL READ_DATA JMP M_LOOP ;----------------------------------------------------- ;写N字节数据子程序 ;查表写数据入24C02 ;----------------------------------------------------- WRITE_DATA: MOV R0,#00H ;数据写入首地址 MOV R1,#72 ;共写入72个字节的数据 MOV DPTR,#TAB ;查表 WR_LOOP: CLR A MOVC A,@A+DPTR MOV B,A LCALL WRITE_BYTE ;将查表结果写入24C02 INC R0 ;地址+1 INC DPTR ;数据指针+1 DJNZ R1,WR_LOOP ;72个数写入完毕? RET ;----------------------------------------------------- ;读N字节数据子程序 ;从24C02读出数据,送P0口显示 ;----------------------------------------------------- READ _DATA: MOV R0,#00H ;设定读取的初始地址 MOV R1,#72 ;设定读取个数 RE_LOOP: LCALL READ_BYTE ;读EEPROM CALL STOP INC R0 ;地址+1 MOV P0,A ;将结果输出到P0显示 MOV R4,#60 ;延时约300ms LCALL DELAY_5MS DJNZ R1,RE_LOOP RET ;---------------------------------------------------- ;写操作子程序 ;输入参数: R0---要写入的地址,B---要写入的数据 ;---------------------------------------------------- WRITE_BYTE: CALL START MOV A,#0A0H CALL SENDBYTE CALL WAITACK MOV A,R0 CALL SENDBYTE CALL WAITACK MOV A,B CALL SENDBYTE CALL WAITACK CALL STOP MOV R4,#1 ;每写入1个字节,延时若干MS CALL DELAY_5MS RET ;---------------------------------------------------- ;读操作子程序 ;输入参数:R0---要读的字节地址, ;输出参数: A---结果 ;---------------------------------------------------- READ_BYTE: CALL START MOV A,#0A0H CALL SENDBYTE CALL WAITACK MOV A,R0 CALL SENDBYTE CALL WAITACK CALL START MOV A,#0A1H CALL SENDBYTE CALL WAITACK CALL RCVBYTE RET ;----------------------------------------------------- ;从IIC总线上接收一个字节数据 ;出口参数:A---接收数据存放在A中 ;----------------------------------------------------- RCVBYTE: MOV R7,#08 ;一个字节共接收8位数据 CLR A SETB SDA ;释放SDA数据线 R_BYTE: CLR SCL NOP NOP NOP NOP SETB SCL ;启动一个时钟周期,读总线 NOP NOP NOP NOP MOV C,SDA ;将SDA状态读入C RLC A ;结果移入A SETB SDA ;释放SDA数据线 DJNZ R7,R_BYTE ;判断8位数据是否接收完全? RET ;---------------------------------------------------- ;向IIC总线发送一个字节数据 ;入口参数:A---待发送数据存放在A中 ;---------------------------------------------------- SENDBYTE: MOV R7,#08 S_BYTE: RLC A MOV SDA,C SETB SCL NOP NOP NOP NOP CLR SCL DJNZ R7,S_BYTE ;8位发送完毕? RET ;----------------------------------------------------- ;等待应答信号 ;等待从机返回一个响应信号 ;----------------------------------------------------- WAITACK: CLR SCL SETB SDA ;释放SDA信号线 NOP NOP SETB SCL NOP NOP NOP MOV C,SDA JC WAITACK ;SDA为低电平,返回了响应信号 CLR SDA CLR SCL RET ;---------------------------------------------------- ;启动信号子程序 ;---------------------------------------------------- START: SETB SDA SETB SCL NOP CLR SDA NOP NOP NOP NOP CLR SCL RET ;---------------------------------------------------- ;停止信号子程序 ;---------------------------------------------------- STOP: CLR SDA NOP SETB SCL NOP NOP NOP NOP SETB SDA NOP NOP CLR SCL CLR SDA RET ;---------------------------------------------------- ;延时5MS子程序 ;输入参数:R4---R4*5MS ;输出参数: 无 ;影响资源: R4,R5,R6等 ;---------------------------------------------------- DELAY_5MS: MOV R6,#10 DE_LP: MOV R5,#250 DJNZ R5,$ DJNZ R6,DE_LP DJNZ R4,DELAY_5MS RET ;---------------------------------------------------- TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH DB 0BFH,0DFH,0EFH,0F7H,0FBH,0FDH,0FEH,0FFH DB 0FEH,0FCH,0F8H,0F0H,0E0H,0C0H,080H,000H DB 080H,0C0H,0E0H,0F0H,0F8H,0FCH,0FEH,0FFH DB 0FCH,0F9H,0F3H,0E7H,0CFH,09FH,03FH DB 09FH,0CFH,0E7H,0F3H,0F9H,0FCH,0FFH DB 0E7H,0DBH,0BDH,07EH,0BDH,0DBH,0E7H,0FFH DB 0E7H,0C3H,081H,000H,081H,0C3H,0E7H,0FFH DB 0AAH,055H,018H,0FFH,0F0H,00FH DB 000H,0FFH,000H,0FFH ;----------------------------------------------------- END
