📄 24c02.lst
字号:
__text_start:
__start:
0033 E5CF LDI R28,0x5F
0034 E0D4 LDI R29,4
0035 BFCD OUT 0x3D,R28
0036 BFDE OUT 0x3E,R29
0037 51C0 SUBI R28,0x10
0038 40D0 SBCI R29,0
0039 EA0A LDI R16,0xAA
003A 8308 STD Y+0,R16
003B 2400 CLR R0
003C E7E2 LDI R30,0x72
003D E0F0 LDI R31,0
003E E010 LDI R17,0
003F 37E3 CPI R30,0x73
0040 07F1 CPC R31,R17
0041 F011 BEQ 0x0044
0042 9201 ST R0,Z+
0043 CFFB RJMP 0x003F
0044 8300 STD Z+0,R16
0045 E5E4 LDI R30,0x54
0046 E0F0 LDI R31,0
0047 E6A0 LDI R26,0x60
0048 E0B0 LDI R27,0
0049 E010 LDI R17,0
004A 36E6 CPI R30,0x66
004B 07F1 CPC R31,R17
004C F021 BEQ 0x0051
004D 95C8 LPM
004E 9631 ADIW R30,1
004F 920D ST R0,X+
0050 CFF9 RJMP 0x004A
0051 940E00C1 CALL _main
_exit:
0053 CFFF RJMP _exit
FILE: E:\MYWORK~1\开发设计\EasyAVR\程序范例\Mega16例程\24C02T~1\24c02.c
(0001) /****************************************Copyright (c)**************************************************
(0002) ** ADEmbed Development Co.,LTD.
(0003) ** http://www.adembed.com
(0004) **--------------File Info-------------------------------------------------------------------------------
(0005) ** File name: 24c02.c
(0006) ** Last modified Date: 2008-12-13
(0007) ** Last Version: 1.0
(0008) ** Descriptions: 24c02 Test.
(0009) **
(0010) **------------------------------------------------------------------------------------------------------
(0011) ** Created by: junbolu
(0012) ** Created date: 2008-12-13
(0013) ** Version: 1.0
(0014) ** Descriptions:
(0015) **
(0016) **------------------------------------------------------------------------------------------------------
(0017) ** Modified by:
(0018) ** Modified date:
(0019) ** Version:
(0020) ** Descriptions:
(0021) **
(0022) **------------------------------------------------------------------------------------------------------
(0023) **ICC-AVR application builder : 2008-12-13
(0024) **Target : M16
(0025) **Crystal: 7.3728Mhz
(0026) **PC0--->SCL PC1--->SDA PD6--->Write_EN
(0027) **
(0028) **描述:按键K0被按下一次,数码管的最低位会加一,并存储在24C02中,下一次系统启动时,会读取此数据并显示。
(0029) **
(0030) **
(0031) **涉及知识点:
(0032) ** I2C
(0033) **
(0034) **
(0035) *******************************************************************************************************/
(0036)
(0037) #include<iom16v.h>
(0038) #include<macros.h>
(0039) #include"Define.h"
(0040)
(0041) #define fose 7372800
(0042)
(0043) #define SCL 0
(0044) #define SDA 1
(0045)
(0046) #define i2c_ddr DDRC
(0047) #define i2c_port PORTC
(0048) #define i2c_pin PINC
(0049)
(0050) #define AT24C02_ADDR 0xA0 //EEPROM设备地址
(0051) //定义I2C的延迟参数
(0052) #define DelayX 100 //7.3M=>1; 8.4M=>2.建议5,因为将来的ClockCPU可以是16M
(0053)
(0054)
(0055) #define SCL_1 {i2c_port|=1<<SCL;Delay_us(DelayX);}
(0056) #define SCL_0 {i2c_port&=~(1<<SCL);Delay_us(DelayX);}
(0057) #define SDA_1 {i2c_port|=1<<SDA;Delay_us(DelayX);}
(0058) #define SDA_0 {i2c_port&=~(1<<SDA);Delay_us(DelayX);}
(0059)
(0060) #define Write_EN_DO DDRD |= (1<<6);
(0061) #define Write_EN_1 PORTD|= (1<<6);
(0062) #define Write_EN_0 PORTD&=~(1<<6);
(0063)
(0064)
(0065) unsigned char DISP_NUM; //显示的位数
(0066) unsigned char BitTab[]={0xFE,0xFD,0xFB,0xF7}; //三位位选码
(0067) unsigned char DispTab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //LED字形码
(0068) unsigned char DISP_DATA[4]={0,0,0,0}; //显示的数字
(0069)
(0070) void I2C_Ini(void);
(0071) void IICStart(void);
(0072) void IICStop(void);
(0073) uint8 IICRecAck(void);
(0074) uint8 IICReceiveByte(void);
(0075) void IICSendByte(uint8 sendbyte);
(0076) void IICNoAck(void);
(0077) void IICACK(void);
(0078) uint8 i2c_Read(uint8 subAddr,uint8 device);
(0079) void i2c_Write(uint8 subAddr,uint8 device,uint8 data);
(0080)
(0081)
(0082)
(0083) void Delay_us(unsigned int time)
(0084) {
(0085) while(time--);
_Delay_us:
time --> R16
0054 0118 MOVW R2,R16
0055 5001 SUBI R16,1
0056 4010 SBCI R17,0
0057 2022 TST R2
0058 F7D9 BNE 0x0054
0059 2033 TST R3
005A F7C9 BNE 0x0054
005B 9508 RET
_Delay_ms:
time --> R20
005C 940E01DB CALL push_gset1
005E 01A8 MOVW R20,R16
(0086) }
(0087)
(0088) void Delay_ms(unsigned int time)
(0089) {
005F C003 RJMP 0x0063
(0090) while(time--)
(0091) {
(0092) Delay_us(1000);
0060 EE08 LDI R16,0xE8
0061 E013 LDI R17,3
0062 DFF1 RCALL _Delay_us
0063 011A MOVW R2,R20
0064 5041 SUBI R20,1
0065 4050 SBCI R21,0
0066 2022 TST R2
0067 F7C1 BNE 0x0060
0068 2033 TST R3
0069 F7B1 BNE 0x0060
006A 940E01DE CALL pop_gset1
006C 9508 RET
(0093) }
(0094) }
(0095) void INT0_Init()
(0096) {
(0097) GIFR |=0X40; //清楚标志位
_INT0_Init:
006D B78A IN R24,0x3A
006E 6480 ORI R24,0x40
006F BF8A OUT 0x3A,R24
(0098) //MCUCR|=0X03; //上升沿触发中断
(0099) MCUCR|=0X02;MCUCR&=~0X01; //下降沿触发中断
0070 B785 IN R24,0x35
0071 6082 ORI R24,2
0072 BF85 OUT 0x35,R24
0073 B785 IN R24,0x35
0074 7F8E ANDI R24,0xFE
0075 BF85 OUT 0x35,R24
(0100) GICR |=0X40; //使能外部中断0
0076 B78B IN R24,0x3B
0077 6480 ORI R24,0x40
0078 BF8B OUT 0x3B,R24
0079 9508 RET
_int0_isr:
007A 940E01F2 CALL push_lset
007C 9721 SBIW R28,1
(0101) }
(0102)
(0103) #pragma interrupt_handler int0_isr:2
(0104) void int0_isr(void)
(0105) {
(0106) DISP_DATA[3]++;
007D 91800071 LDS R24,DISP_DATA+3
007F 5F8F SUBI R24,0xFF
0080 93800071 STS DISP_DATA+3,R24
(0107) if(DISP_DATA[3]>9)
0082 E089 LDI R24,0x9
0083 90200071 LDS R2,DISP_DATA+3
0085 1582 CP R24,R2
0086 F418 BCC 0x008A
(0108) {
(0109) DISP_DATA[3]=0;
0087 2422 CLR R2
0088 92200071 STS DISP_DATA+3,R2
(0110) }
(0111) Write_EN_0;
008A 9896 CBI 0x12,6
(0112) i2c_Write(0x02,AT24C02_ADDR,DISP_DATA[3]);
008B 90200071 LDS R2,DISP_DATA+3
008D 8228 STD Y+0,R2
008E EA20 LDI R18,0xA0
008F E002 LDI R16,2
0090 D11B RCALL _i2c_Write
(0113) Write_EN_1;
0091 9A96 SBI 0x12,6
0092 9621 ADIW R28,1
0093 940E0209 CALL pop_lset
0095 9518 RETI
(0114) }
(0115) //显示函数,DISP_NUM决定显示哪个LED
(0116) //采用共阴LED动态显示方法,定时中断函数里面调用
(0117) void Display(void)
(0118) {
(0119) PORTA=0x00; //清除显示再位选
_Display:
0096 2422 CLR R2
0097 BA2B OUT 0x1B,R2
(0120) PORTB=BitTab[DISP_NUM]; //PB口接位选
0098 E680 LDI R24,0x60
0099 E090 LDI R25,0
009A 91E00072 LDS R30,DISP_NUM
009C 27FF CLR R31
009D 0FE8 ADD R30,R24
009E 1FF9 ADC R31,R25
009F 8020 LDD R2,Z+0
00A0 BA28 OUT 0x18,R2
(0121) PORTA=DispTab[DISP_DATA[DISP_NUM]]; //PA口接LED的段码
00A1 E68E LDI R24,0x6E
00A2 E090 LDI R25,0
00A3 91E00072 LDS R30,DISP_NUM
00A5 27FF CLR R31
00A6 0FE8 ADD R30,R24
00A7 1FF9 ADC R31,R25
00A8 81E0 LDD R30,Z+0
00A9 27FF CLR R31
00AA E684 LDI R24,0x64
00AB E090 LDI R25,0
00AC 0FE8 ADD R30,R24
00AD 1FF9 ADC R31,R25
00AE 8020 LDD R2,Z+0
00AF BA2B OUT 0x1B,R2
(0122)
(0123)
(0124) DISP_NUM++; //先显示高位,再显示低位
00B0 91800072 LDS R24,DISP_NUM
00B2 5F8F SUBI R24,0xFF
00B3 93800072 STS DISP_NUM,R24
(0125) if(DISP_NUM==4)
00B5 3084 CPI R24,4
00B6 F419 BNE 0x00BA
(0126) DISP_NUM=0;
00B7 2422 CLR R2
00B8 92200072 STS DISP_NUM,R2
00BA 9508 RET
_timer0comp:
00BB 940E01F2 CALL push_lset
(0127) }
(0128)
(0129) #pragma interrupt_handler timer0comp:20
(0130) void timer0comp (void)
(0131) {
(0132) Display();
00BD DFD8 RCALL _Display
00BE 940E0209 CALL pop_lset
00C0 9518 RETI
(0133) }
(0134)
(0135) void main(void)
(0136) {
(0137)
(0138) DDRA=0XFF;
_main:
00C1 EF8F LDI R24,0xFF
00C2 BB8A OUT 0x1A,R24
(0139) PORTA=0X00;
00C3 2422 CLR R2
00C4 BA2B OUT 0x1B,R2
(0140) DDRB=0X0F;
00C5 E08F LDI R24,0xF
00C6 BB87 OUT 0x17,R24
(0141) PORTB=0X00;
00C7 BA28 OUT 0x18,R2
(0142)
(0143) //按键0端口初始化
(0144) DDRD &=~0x04; //设置PD2为输入
00C8 988A CBI 0x11,2
(0145) PORTD|=0x04; //设置PD2为上拉
00C9 9A92 SBI 0x12,2
(0146)
(0147) INT0_Init(); //TART初始化
00CA DFA2 RCALL _INT0_Init
(0148)
(0149) //t/c0初始化(10ms)
(0150) TCCR0=0X0d;
00CB E08D LDI R24,0xD
00CC BF83 OUT 0x33,R24
(0151) TCNT0=0X00;
00CD 2422 CLR R2
00CE BE22 OUT 0x32,R2
(0152) OCR0=0X48;
00CF E488 LDI R24,0x48
00D0 BF8C OUT 0x3C,R24
(0153) TIMSK=0X02;
00D1 E082 LDI R24,2
00D2 BF89 OUT 0x39,R24
(0154)
(0155) //asm("sei");
(0156) SEI(); //全局中断使能
00D3 9478 BSET 7
(0157)
(0158) I2C_Ini();
00D4 D009 RCALL _I2C_Ini
(0159)
(0160) Write_EN_DO;
00D5 9A8E SBI 0x11,6
(0161) Write_EN_1;
00D6 9A96 SBI 0x12,6
(0162) DISP_DATA[3]=i2c_Read(0x02,AT24C02_ADDR);
00D7 EA20 LDI R18,0xA0
00D8 E002 LDI R16,2
00D9 D0A8 RCALL _i2c_Read
00DA 93000071 STS DISP_DATA+3,R16
(0163)
(0164) for(;;)
00DC CFFF RJMP 0x00DC
00DD 9508 RET
(0165) {
(0166)
(0167) }
(0168) }
(0169)
(0170)
(0171) //=======================================================================
(0172) //初始化端口
(0173) void I2C_Ini(void)
(0174) {
(0175) i2c_ddr|=(1<<SCL); //SCK为输出
_I2C_Ini:
00DE 9AA0 SBI 0x14,0
(0176) i2c_ddr|=(1<<SDA); //SDA为双向的,先设置为输出
00DF 9AA1 SBI 0x14,1
00E0 9508 RET
(0177)
(0178)
(0179) }
(0180) //=======================================================================
(0181) //启动总线。根据IIC协议,SCL为1时,SDA从1转变为0。
(0182) void IICStart(void)
(0183) { SCL_0;
_IICStart:
00E1 98A8 CBI 0x15,0
00E2 E604 LDI R16,0x64
00E3 E010 LDI R17,0
00E4 DF6F RCALL _Delay_us
(0184)
(0185) SDA_1;
00E5 9AA9 SBI 0x15,1
00E6 E604 LDI R16,0x64
00E7 E010 LDI R17,0
00E8 DF6B RCALL _Delay_us
(0186) SCL_1;
00E9 9AA8 SBI 0x15,0
00EA E604 LDI R16,0x64
00EB E010 LDI R17,0
00EC DF67 RCALL _Delay_us
(0187) SDA_0;
00ED 98A9 CBI 0x15,1
00EE E604 LDI R16,0x64
00EF E010 LDI R17,0
00F0 DF63 RCALL _Delay_us
(0188) SCL_0;
00F1 98A8 CBI 0x15,0
00F2 E604 LDI R16,0x64
00F3 E010 LDI R17,0
00F4 DF5F RCALL _Delay_us
00F5 9508 RET
(0189) }
(0190) //=======================================================================
(0191) //停止IIC总线。根据IIC协议,SCL为1时,SDA从0转变为1。
(0192) void IICStop(void)
(0193) {
(0194) SCL_0;
_IICStop:
00F6 98A8 CBI 0x15,0
00F7 E604 LDI R16,0x64
00F8 E010 LDI R17,0
00F9 DF5A RCALL _Delay_us
(0195) SDA_0;
00FA 98A9 CBI 0x15,1
00FB E604 LDI R16,0x64
00FC E010 LDI R17,0
00FD DF56 RCALL _Delay_us
(0196) SCL_1;
00FE 9AA8 SBI 0x15,0
00FF E604 LDI R16,0x64
0100 E010 LDI R17,0
0101 DF52 RCALL _Delay_us
(0197) SDA_1;
0102 9AA9 SBI 0x15,1
0103 E604 LDI R16,0x64
0104 E010 LDI R17,0
0105 DF4E RCALL _Delay_us
0106 9508 RET
_IICRecAck:
ack --> R20
0107 940E01DB CALL push_gset1
(0198) //SCL_0;
(0199) }
(0200) //=======================================================================
(0201) //检查应答位,向I2C写数据时,I2C设备(EEPROM)正常接受到数据后在第9周期发出0应答,
(0202) //如果不正常接受到数据,则不以0应答而进入待命状态。
(0203) //写数据后需检查I2C设备是否有0应答。
(0204) unsigned char IICRecAck(void)
(0205) {
(0206) uint8 ack;
(0207)
(0208) SCL_0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -