📄 light.lst
字号:
010B 99E1 SBIC 0x1C,1
010C CFFE RJMP _rom_write
(0006) EEAR=Address;
010D BB1F OUT 0x1F,R17
010E BB0E OUT 0x1E,R16
(0007) EEDR=Data;
010F BB2D OUT 0x1D,R18
(0008) EECR|=(1<<EEMWE);
0110 9AE2 SBI 0x1C,2
(0009) EECR|=(1<<EEWE);
0111 9AE1 SBI 0x1C,1
0112 9508 RET
(0010) }
(0011) unsigned char rom_read(unsigned int Address)
(0012) {
(0013) CLI();
_rom_read:
Address --> R16
0113 94F8 BCLR 7
(0014) while(EECR&(1<<EEWE));
0114 99E1 SBIC 0x1C,1
0115 CFFE RJMP 0x0114
(0015) EEAR=Address;
0116 BB1F OUT 0x1F,R17
0117 BB0E OUT 0x1E,R16
(0016) EECR|=(1<<EERE);
0118 9AE0 SBI 0x1C,0
(0017) SEI();
0119 9478 BSET 7
(0018) return EEDR;
011A B30D IN R16,0x1D
011B 9508 RET
FILE: G:\Mega8程序\TCXO评估板\LedShow\I2C.c
(0001) /*******************************************************
(0002) 本部分为TWI总线的被控器部分程序,可以完成被控接收、被控发送数据
(0003) 其工作方式与At240×系列的EEPROM的字节读写相同
(0004) 目前问题是EEPROM的读写速度太慢,无法跟上TWI总线速度。
(0005) *///////////////////////////////////////////////////////
(0006)
(0007) #include<iom8v.h>
(0008) #include <macros.h>
(0009) /* AT2402C地址
(0010) 1 0 1 0 A2 A1 A0 R/W
(0011) 前4位为AT240X系列的特征字
(0012) 后3位为可编程位
(0013) 最后一位为读写位
(0014) */
(0015) #define rd_device_add 0xa1 //读地址:0b10100001
(0016) #define wr_device_add 0xa0 //写地址:0b10100000
(0017)
(0018) /*TWI状态定义----MT 主方式传输 MR 主方式接收*/
(0019) #define START 0x08
(0020) #define RE_START 0x10
(0021)
(0022) #define MT_SLA_ACK 0x18
(0023) #define MT_SLA_NOACK 0x20
(0024) #define MT_DATA_ACK 0x28
(0025) #define MT_DATA_NOACK 0x30
(0026)
(0027) #define MR_SLA_ACK 0x40
(0028) #define MR_SLA_NOACK 0x48
(0029) #define MR_DATA_ACK 0x50
(0030) #define MR_DATA_NOACK 0x58
(0031)
(0032) //SR-从机方式接收 ST-从机方式传输 ALL-广播 NOCTRL-主机丢失控制权
(0033) #define SR_SLA_ACK 0x60
(0034) #define SR_SLA_ACK_NOCTRL 0x68
(0035) #define SR_ALL_ACK 0x70
(0036) #define SR_ALL_ACK_NOCTRL 0x78
(0037) #define SR_DATA_ACK 0X80
(0038) #define SR_DATA_NOACK 0X88
(0039) #define SR_ALL_DATA_ACK 0x90
(0040) #define SR_ALL_DATA_NOACK 0x98
(0041) #define SR_STOP_RESTART 0xa0
(0042)
(0043) #define ST_SLA_ACK 0xa8
(0044) #define ST_SLA_ACK_NOCTRL 0xb0
(0045) #define ST_DATA_ACK 0xb8
(0046) #define ST_DATA_NOACK 0xc0
(0047) #define ST_LAST_DATA_ACK 0xc8
(0048)
(0049) ///////////////////////////////////////////////////////////
(0050) #define EE_READ 0xf0
(0051) #define EE_READ_OK 0x50
(0052) #define EE_WRITE 0x0f
(0053) #define EE_WRITE_OK 0x05
(0054) #define EE_WRITE_OVER 0xa5
(0055)
(0056) #define TestAck() (TWSR&0xf8)
(0057) //TWSR--I2C状态寄存器,检查TWI状态,应该将预分频位屏蔽(第三位是保留位)
(0058)
(0059) #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE))
(0060) //清除中断标志位,在总线上发出起始信号,激活TWI功能,开放TWI中断
(0061) #define Stop() (TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))&(~(1<<TWIE)))
(0062) //清除中断标志位,在总线上发出终止信号,激活TWI功能,关闭TWI中断
(0063) #define MT_NACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
(0064) //清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下不对SDA线作应答
(0065) #define MT_ACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA))
(0066) //清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下对SDA线作应答
(0067) #define TWItransmit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}
(0068) //写入8位数据到数据寄存器中,同时清除中断标志位,使能TWI功能,开放TWI中断
(0069)
(0070) extern char cDataBuff[];
(0071) extern void rom_write(unsigned int Address,unsigned char Data);
(0072) extern unsigned char rom_read(unsigned int Address);
(0073)
(0074) unsigned char charData;//TWI中断中,传送的数据
(0075) unsigned char charAddr;//TWI中断中,数据所处的EEPROM地址
(0076) unsigned char charState;//TWI中断中,中断所处的状态
(0077)
(0078) void TWI_init(void)
(0079) {
(0080) DDRC&=0b11001111;//设置PC4、PC5为输入
_TWI_init:
011C B384 IN R24,0x14
011D 7C8F ANDI R24,0xCF
011E BB84 OUT 0x14,R24
(0081) PORTC|=0b00110000;//将SDA、SCL线拉高(内置上拉电阻)
011F B385 IN R24,0x15
0120 6380 ORI R24,0x30
0121 BB85 OUT 0x15,R24
(0082) charState=EE_READ;
0122 EF80 LDI R24,0xF0
0123 9380008C STS charState,R24
(0083) TWBR=0x00;//波特率寄存器,主机正常情况下应不小于10
0125 2422 CLR R2
0126 B820 OUT 0x00,R2
(0084) TWSR=0x00;//TWI状态寄存器,时钟分频值1
0127 B821 OUT 0x01,R2
(0085) TWAR=0xa0;/*被控器地址寄存器。0xa0为AT2402的地址,可以用ATMEGA8来模拟AT2402。
0128 EA80 LDI R24,0xA0
0129 B982 OUT 0x02,R24
(0086) 作为从机,应该将被控器的地址写入。注意不要和其他器件相同*/
(0087) TWCR=(TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA));//清除中断标志位,使能TWI功能,开放TWI中断
012A EC85 LDI R24,0xC5
012B BF86 OUT 0x36,R24
012C BF86 OUT 0x36,R24
012D 9508 RET
_TWI_Ready:
charTemp --> R20
TWI_STATE --> R22
012E 922A ST R2,-Y
012F 923A ST R3,-Y
0130 930A ST R16,-Y
0131 931A ST R17,-Y
0132 938A ST R24,-Y
0133 939A ST R25,-Y
0134 93EA ST R30,-Y
0135 93FA ST R31,-Y
0136 B62F IN R2,0x3F
0137 922A ST R2,-Y
0138 D1C2 RCALL push_gset2
(0088) }
(0089) #pragma interrupt_handler TWI_Ready:iv_TWI//TWI中断处理
(0090) void TWI_Ready(void)
(0091) {
(0092) static unsigned char charIndex=0;
(0093) unsigned char charTemp;
(0094) unsigned char TWI_STATE;
(0095) TWI_STATE=TestAck();
0139 B161 IN R22,0x01
013A 7F68 ANDI R22,0xF8
(0096) switch (TWI_STATE)//检查状态标志字
013B 2F46 MOV R20,R22
013C 2755 CLR R21
013D 3A40 CPI R20,0xA0
013E E0E0 LDI R30,0
013F 075E CPC R21,R30
0140 F409 BNE 0x0142
0141 C103 RJMP 0x0245
0142 EA80 LDI R24,0xA0
0143 E090 LDI R25,0
0144 1784 CP R24,R20
0145 0795 CPC R25,R21
0146 F074 BLT 0x0155
0147 3640 CPI R20,0x60
0148 E0E0 LDI R30,0
0149 075E CPC R21,R30
014A F101 BEQ 0x016B
014B 3640 CPI R20,0x60
014C E0E0 LDI R30,0
014D 075E CPC R21,R30
014E F40C BGE 0x0150
014F C111 RJMP 0x0261
0150 3840 CPI R20,0x80
0151 E0E0 LDI R30,0
0152 075E CPC R21,R30
0153 F0D1 BEQ 0x016E
0154 C10C RJMP 0x0261
0155 3B48 CPI R20,0xB8
0156 E0E0 LDI R30,0
0157 075E CPC R21,R30
0158 F409 BNE 0x015A
0159 C0F3 RJMP 0x024D
015A EB88 LDI R24,0xB8
015B E090 LDI R25,0
015C 1784 CP R24,R20
015D 0795 CPC R25,R21
015E F034 BLT 0x0165
015F 3A48 CPI R20,0xA8
0160 E0E0 LDI R30,0
0161 075E CPC R21,R30
0162 F409 BNE 0x0164
0163 C0E4 RJMP 0x0248
0164 C0FC RJMP 0x0261
0165 3C40 CPI R20,0xC0
0166 E0E0 LDI R30,0
0167 075E CPC R21,R30
0168 F409 BNE 0x016A
0169 C0F4 RJMP 0x025E
016A C0F6 RJMP 0x0261
(0097) {
(0098) case SR_SLA_ACK:
(0099) {
(0100) MT_ACK;
016B EC85 LDI R24,0xC5
016C BF86 OUT 0x36,R24
(0101) }
(0102) break;
016D C150 RJMP 0x02BE
(0103) case SR_DATA_ACK:
(0104) {
(0105) switch (charState)
016E 9140008C LDS R20,charState
0170 2755 CLR R21
0171 3540 CPI R20,0x50
0172 E0E0 LDI R30,0
0173 075E CPC R21,R30
0174 F0B9 BEQ 0x018C
0175 3540 CPI R20,0x50
0176 E0E0 LDI R30,0
0177 075E CPC R21,R30
0178 F40C BGE 0x017A
0179 C144 RJMP 0x02BE
017A 3F40 CPI R20,0xF0
017B E0E0 LDI R30,0
017C 075E CPC R21,R30
017D F009 BEQ 0x017F
017E C13F RJMP 0x02BE
(0106) {
(0107) case EE_READ://进入开始读取数据状态,此处即将读取的数据为ROM的Index
(0108) {
(0109) PORTC^=(0b00001000);//闪亮LED
017F E088 LDI R24,0x8
0180 B225 IN R2,0x15
0181 2628 EOR R2,R24
0182 BA25 OUT 0x15,R2
(0110) charAddr=TWDR;
0183 B023 IN R2,0x03
0184 9220008D STS charAddr,R2
(0111) MT_ACK;
0186 EC85 LDI R24,0xC5
0187 BF86 OUT 0x36,R24
(0112) charState=EE_READ_OK;
0188 E580 LDI R24,0x50
0189 9380008C STS charState,R24
(0113) }
(0114) break;
018B C132 RJMP 0x02BE
(0115) case EE_READ_OK://进入读取数据完成状态此处即将读取的数据为ROM->Index的数据
(0116) {
(0117) charData=TWDR;
018C B023 IN R2,0x03
018D 9220008E STS charData,R2
(0118) MT_ACK;
018F EC85 LDI R24,0xC5
0190 BF86 OUT 0x36,R24
(0119) //rom_write((unsigned char)charAddr,charData);
(0120) charState=EE_READ;
0191 EF80 LDI R24,0xF0
0192 9380008C STS charState,R24
(0121) charIndex+=3;
0194 9180008B LDS R24,charIndex
0196 5F8D SUBI R24,0xFD
0197 9380008B STS charIndex,R24
(0122) charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
0199 718F ANDI R24,0x1F
019A 9380008B STS charIndex,R24
(0123) cDataBuff[charIndex--]=0x0a;//间隔空格符
019C 2E28 MOV R2,R24
019D 2433 CLR R3
019E 5081 SUBI R24,1
019F 9380008B STS charIndex,R24
01A1 E681 LDI R24,0x61
01A2 E090 LDI R25,0
01A3 2DE2 MOV R30,R2
01A4 27FF CLR R31
01A5 0FE8 ADD R30,R24
01A6 1FF9 ADC R31,R25
01A7 E08A LDI R24,0xA
01A8 8380 STD Z+0,R24
(0124) charTemp=charAddr%10;
01A9 E01A LDI R17,0xA
01AA 9100008D LDS R16,charAddr
01AC D11D RCALL mod8u
01AD 2F40 MOV R20,R16
(0125) charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
01AE 9180008B LDS R24,charIndex
01B0 718F ANDI R24,0x1F
01B1 9380008B STS charIndex,R24
(0126) cDataBuff[charIndex--]=charTemp;
01B3 2E28 MOV R2,R24
01B4 2433 CLR R3
01B5 5081 SUBI R24,1
01B6 9380008B STS charIndex,R24
01B8 E681 LDI R24,0x61
01B9 E090 LDI R25,0
01BA 2DE2 MOV R30,R2
01BB 27FF CLR R31
01BC 0FE8 ADD R30,R24
01BD 1FF9 ADC R31,R25
01BE 8340 STD Z+0,R20
(0127) charAddr/=10;
01BF E01A LDI R17,0xA
01C0 9100008D LDS R16,charAddr
01C2 D109 RCALL div8u
01C3 9300008D STS charAddr,R16
(0128) charTemp=charAddr%10;
01C5 E01A LDI R17,0xA
01C6 D103 RCALL mod8u
01C7 2F40 MOV R20,R16
(0129) charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
01C8 9180008B LDS R24,charIndex
01CA 718F ANDI R24,0x1F
01CB 9380008B STS charIndex,R24
(0130) cDataBuff[charIndex--]=charTemp;
01CD 2E28 MOV R2,R24
01CE 2433 CLR R3
01CF 5081 SUBI R24,1
01D0 9380008B STS charIndex,R24
01D2 E681 LDI R24,0x61
01D3 E090 LDI R25,0
01D4 2DE2 MOV R30,R2
01D5 27FF CLR R31
01D6 0FE8 ADD R30,R24
01D7 1FF9 ADC R31,R25
01D8 8340 STD Z+0,R20
(0131) charAddr/=10;
01D9 E01A LDI R17,0xA
01DA 9100008D LDS R16,charAddr
01DC D0EF RCALL div8u
01DD 9300008D STS charAddr,R16
(0132) cDataBuff[charIndex]=charAddr;
01DF E681 LDI R24,0x61
01E0 E090 LDI R25,0
01E1 91E0008B LDS R30,charIndex
01E3 27FF CLR R31
01E4 0FE8 ADD R30,R24
01E5 1FF9 ADC R31,R25
01E6 2E20 MOV R2,R16
01E7 8220 STD Z+0,R2
(0133) charIndex+=4;//指向末尾空位
01E8 9180008B LDS R24,charIndex
01EA 5F8C SUBI R24,0xFC
01EB 9380008B STS charIndex,R24
(0134) charIndex+=3;
01ED 5F8D SUBI R24,0xFD
01EE 9380008B STS charIndex,R24
(0135) charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -