📄 max5478.s
字号:
.module MAX5478.C
.area text(rom, con, rel)
.dbfile E:\程序与资料\dpj\AVR\自己写的AVR\MAX5478\MAX5478.C
.dbfunc e Delayms _Delayms fV
; i -> R10,R11
; j -> R12,R13
; MS -> R16,R17
.even
_Delayms::
xcall push_xgset003C
.dbline -1
.dbline 23
; /***************MAX5478数字电位器-I2C**********************/
; #include <iom16v.h> //包含型号头文件
; #include <macros.h> //包含"位"操作头文件
; #include <stdio.h> //标准输入输出头文件
; /******************数据类型宏定义******************/
; #define TRUE 1
; #define FALSE 0
; #define uchar unsigned char
; #define uint unsigned int
; //******************按键常量******************/
; #define KEY_DDR DDRD //按键方向定义
; #define KEY_PORTO PORTD //按键端口输出定义
; #define KEY_PORTI PIND //按键端口输入定义
; #define OUT 0xFF //输出常量
; #define IN 0xF0 //输入常量
; /*******************************************
; 函数名称: Delayms
; 功 能: 延时指定毫秒(12M晶振)
; 参 数: MS--延时的毫秒数
; 返回值 : 无
; /********************************************/
; void Delayms(uint MS)
; {
.dbline 25
; uint i,j;
; for( i=0;i<MS;i++)
clr R10
clr R11
xjmp L5
L2:
.dbline 26
; for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
clr R12
clr R13
xjmp L9
L6:
.dbline 26
L7:
.dbline 26
movw R24,R12
adiw R24,1
movw R12,R24
L9:
.dbline 26
movw R24,R12
cpi R24,117
ldi R30,4
cpc R25,R30
brlo L6
X0:
L3:
.dbline 25
movw R24,R10
adiw R24,1
movw R10,R24
L5:
.dbline 25
cp R10,R16
cpc R11,R17
brlo L2
X1:
.dbline -2
L1:
.dbline 0 ; func end
xjmp pop_xgset003C
.dbsym r i 10 i
.dbsym r j 12 i
.dbsym r MS 16 i
.dbend
.dbfile E:\程序与资料\dpj\AVR\自己写的AVR\MAX5478\Skey.C
.dbfunc e Skey_press _Skey_press fc
; pressed -> R16
.even
_Skey_press::
.dbline -1
.dbline 10
;
;
; /*******************************************
; 函数名称: Skey_press
; 功 能: 检测是否有键按下
; 参 数: 无
; 返回值 : pressed--有键按下时为TRUE,否则为FALSE
; /********************************************/
; uchar Skey_press(void)
; {
.dbline 12
; uchar pressed;
; KEY_DDR=OUT; //定义数据端口为输出
ldi R24,255
out 0x11,R24
.dbline 13
; KEY_PORTO|=0x0F; //输出数据(输出检测码)
in R24,0x12
ori R24,15
out 0x12,R24
.dbline 14
; KEY_DDR=IN; //定义数据端口为输入
ldi R24,240
out 0x11,R24
.dbline 15
; if((KEY_PORTI&0x0F)!=0x0F) //检测是否有键按下
in R24,0x10
andi R24,15
cpi R24,15
breq L11
X2:
.dbline 16
; pressed=TRUE; //有键按下则返回TRUE
ldi R16,1
xjmp L12
L11:
.dbline 18
; else
; pressed=FALSE; //无键按下则返回FALSE
clr R16
L12:
.dbline 19
; KEY_DDR=OUT; //数据端口还原为输出
ldi R24,255
out 0x11,R24
.dbline 20
; return pressed;
.dbline -2
L10:
.dbline 0 ; func end
ret
.dbsym r pressed 16 c
.dbend
.dbfunc e Skey_scan _Skey_scan fc
; keycode -> R10
.even
_Skey_scan::
xcall push_xgset003C
.dbline -1
.dbline 29
; }
; /*******************************************
; 函数名称: Skey_scan
; 功 能: 扫描所按的键并返回键值
; 参 数: 无
; 返回值 : keycode--被按下键值
; /********************************************/
; uchar Skey_scan(void)
; {
.dbline 30
; uchar keycode=0xFF;
ldi R24,255
mov R10,R24
.dbline 31
; Delayms(15); //延时消抖
ldi R16,15
ldi R17,0
xcall _Delayms
.dbline 32
; if(Skey_press()==TRUE) //如果有键按下
xcall _Skey_press
cpi R16,1
brne L14
X3:
.dbline 33
; {
.dbline 34
; KEY_DDR=IN; //定义数据端口为输入
ldi R24,240
out 0x11,R24
.dbline 35
; keycode=KEY_PORTI; //读入原始键码
in R10,0x10
.dbline 36
; keycode&=0x0F; //屏蔽高4位
mov R24,R10
andi R24,15
mov R10,R24
.dbline 37
; switch(keycode) //翻译原始键码为0~3
mov R12,R24
clr R13
movw R24,R12
cpi R24,7
ldi R30,0
cpc R25,R30
breq L22
X4:
cpi R24,11
ldi R30,0
cpc R25,R30
breq L21
X5:
cpi R24,13
ldi R30,0
cpc R25,R30
breq L20
X6:
cpi R24,14
ldi R30,0
cpc R25,R30
breq L19
X7:
xjmp L16
L19:
.dbline 40
; {
; case 0x0E:
; keycode=0;
clr R10
.dbline 41
; break;
xjmp L17
L20:
.dbline 43
; case 0x0D:
; keycode=1;
clr R10
inc R10
.dbline 44
; break;
xjmp L17
L21:
.dbline 46
; case 0x0B:
; keycode=2;
ldi R24,2
mov R10,R24
.dbline 47
; break;
xjmp L17
L22:
.dbline 49
; case 0x07:
; keycode=3;
ldi R24,3
mov R10,R24
.dbline 50
; break;
xjmp L17
L16:
.dbline 52
; default:
; keycode=0x00;
clr R10
.dbline 53
; }
L17:
L23:
.dbline 55
; do
; {
.dbline 56
; }while(Skey_press()==TRUE); //等待按键释放(为了防止按一次,执行多次的现象)
L24:
.dbline 56
xcall _Skey_press
cpi R16,1
breq L23
X8:
.dbline 57
; }
L14:
.dbline 58
; return keycode;
mov R16,R10
.dbline -2
L13:
.dbline 0 ; func end
xjmp pop_xgset003C
.dbsym r keycode 10 c
.dbend
.dbfile E:\程序与资料\dpj\AVR\自己写的AVR\MAX5478\MAX5478.C
.dbfunc e Twi_init _Twi_init fV
.even
_Twi_init::
.dbline -1
.dbline 45
; }
; //************************************************
; #include "Skey.C" //包含键盘扫描函数
; /******************TWI(IIC)常量******************/
; #define START 0x08 //START信号发送完毕状态
; #define MT_SLA_ACK 0x18 //从器件地址发送,返回ACK
; #define MT_SLA_NOACK 0x20 //从器件地址发送,但是返回NOACK
; #define MT_DATA_ACK 0x28 //数据已发送,返回ACK
; #define MT_DATA_NOACK 0x30 //数据已发送,返回NOACK
;
; #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //产生START信号
; #define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //产生STOP信号
; #define Wait() while(!(TWCR&(1<<TWINT))) //等待当前操作完成
; #define TestACK() (TWSR&0xF8) //取出状态码
; #define SetACK() (TWCR|=(1<<TWEA)) //产生ACK
; #define Writebyte(twi_d) {TWDR=(twi_d);TWCR=(1<<TWINT)|(1<<TWEN);} //发送一个字节(twi_d为写入的数据)
; //************************************************************************************************************
; void Twi_init(void)
; {
.dbline 46
; TWBR= 0x20; //设置波特率
ldi R24,32
out 0x0,R24
.dbline 47
; TWSR= 0x00; //设置预分频比
clr R2
out 0x1,R2
.dbline 48
; TWCR= 0x44; //使能应答,使能TWI
ldi R24,68
out 0x36,R24
.dbline -2
L26:
.dbline 0 ; func end
ret
.dbend
.dbfunc e MAX5478_writeB _MAX5478_writeB fc
; success -> R10
; rdata -> y+6
; cmd -> R12
; devadd -> R14
.even
_MAX5478_writeB::
xcall push_xgset00FC
mov R12,R18
mov R14,R16
.dbline -1
.dbline 60
; }
;
; /*******************************************
; 函数名称: MAX5478_writeB
; 功 能: 向MAX5478写入电阻值数据
; 参 数: devadd--器件地址
; cmd--控制命令
; rdata--电阻数据
; 返回值 : success--数据成功标志(为TRUE时写入成功,为FALSE时失败)
; /********************************************/
; uchar MAX5478_writeB(uchar devadd,uchar cmd,uchar rdata)
; {
.dbline 61
; uchar success=FALSE; //默认返回是写入失败
clr R10
.dbline 62
; Start(); //产生START信号
ldi R24,164
out 0x36,R24
L28:
.dbline 63
; Wait(); //等待START信号发送完毕
L29:
.dbline 63
in R2,0x36
sbrs R2,7
rjmp L28
X9:
.dbline 64
; if(TestACK()!=START) //检查是否是START信号发送完毕状态
in R24,0x1
andi R24,248
cpi R24,8
breq L31
X10:
.dbline 65
; {
.dbline 66
; success=FALSE; //如果不是,则返回写入失败
clr R10
.dbline 67
; return success;
mov R16,R10
xjmp L27
L31:
.dbline 69
; }
; Writebyte(devadd); //发送从器件地址
.dbline 69
out 0x3,R14
.dbline 69
ldi R24,132
out 0x36,R24
.dbline 69
.dbline 69
L33:
.dbline 70
; Wait(); //等待发送完毕
L34:
.dbline 70
in R2,0x36
sbrs R2,7
rjmp L33
X11:
.dbline 71
; if(TestACK()!=MT_SLA_ACK)//检查是否是从器件地址发送完毕状态
in R24,0x1
andi R24,248
cpi R24,24
breq L36
X12:
.dbline 72
; {
.dbline 73
; success=FALSE; //如果不是,则返回写入失败
clr R10
.dbline 74
; return success;
mov R16,R10
xjmp L27
L36:
.dbline 76
; }
; Writebyte(cmd); //发送MAX5478的命令字节(具体含义请参看MAX5478的数据手册)
.dbline 76
out 0x3,R12
.dbline 76
ldi R24,132
out 0x36,R24
.dbline 76
.dbline 76
L38:
.dbline 77
; Wait(); //等待发送完毕
L39:
.dbline 77
in R2,0x36
sbrs R2,7
rjmp L38
X13:
.dbline 78
; if(TestACK()!=MT_DATA_ACK)//检查是否是数据发送完毕
in R24,0x1
andi R24,248
cpi R24,40
breq L41
X14:
.dbline 79
; {
.dbline 80
; success=FALSE; //如果不是,则返回写入失败
clr R10
.dbline 81
; return success;
mov R16,R10
xjmp L27
L41:
.dbline 83
; }
; Writebyte(rdata); //发送电阻值数据
.dbline 83
ldd R0,y+6
out 0x3,R0
.dbline 83
ldi R24,132
out 0x36,R24
.dbline 83
.dbline 83
L43:
.dbline 84
; Wait(); //等待发送完毕
L44:
.dbline 84
in R2,0x36
sbrs R2,7
rjmp L43
X15:
.dbline 85
; if(TestACK()!=MT_DATA_ACK)//检查是否是数据发送完毕
in R24,0x1
andi R24,248
cpi R24,40
breq L46
X16:
.dbline 86
; {
.dbline 87
; success=FALSE; //如果不是,则返回写入失败
clr R10
.dbline 88
; return success;
mov R16,R10
xjmp L27
L46:
.dbline 90
; }
; Stop(); //对MAX5478的一次操作完毕,发送STOP信号
ldi R24,148
out 0x36,R24
.dbline 91
; Delayms(10); //等待发送完毕
ldi R16,10
ldi R17,0
xcall _Delayms
.dbline 92
; success=TRUE; //本次写入成功
clr R10
inc R10
.dbline 93
; return success; //返回写入成功状态
mov R16,R10
.dbline -2
L27:
.dbline 0 ; func end
xjmp pop_xgset00FC
.dbsym r success 10 c
.dbsym l rdata 6 c
.dbsym r cmd 12 c
.dbsym r devadd 14 c
.dbend
.dbfunc e main _main fV
; data -> R10
; i -> R12
.even
_main::
sbiw R28,1
.dbline -1
.dbline 102
; }
; /*******************************************
; 函数名称: main
; 功 能: 按键更新数字电位器的阻值(电阻是A和W端的阻值,默认B端是开路的)
; 参 数: 无
; 返回值 : 无
; /********************************************/
; void main(void)
; {
.dbline 103
; uchar i,data=255; //初始电阻是满量程
ldi R24,255
mov R10,R24
.dbline 105
;
; Twi_init( ); //初始化TWI
xcall _Twi_init
.dbline 106
; MAX5478_writeB(0x50,0x13,data); //设置初始电阻
std y+0,R10
ldi R18,19
ldi R16,80
xcall _MAX5478_writeB
xjmp L50
L49:
.dbline 108
; while(1)
; {
.dbline 109
; if(Skey_press()) //是否有按键按下
xcall _Skey_press
tst R16
breq L52
X17:
.dbline 110
; {
.dbline 111
; i=Skey_scan(); //扫描并反回翻译后的键码
xcall _Skey_scan
mov R12,R16
.dbline 112
; switch(i)
clr R13
tst R12
brne X18
tst R13
breq L57
X18:
movw R24,R12
cpi R24,1
ldi R30,0
cpc R25,R30
breq L58
X19:
cpi R24,2
ldi R30,0
cpc R25,R30
breq L59
X20:
cpi R24,3
ldi R30,0
cpc R25,R30
breq L60
X21:
xjmp L54
L57:
.dbline 115
; {
; case 0: //S1键按下,减少电阻的数字量(MAX5478的特性是减少电阻的数字量,阻值增加)
; data-=5;
mov R24,R10
subi R24,5
mov R10,R24
.dbline 116
; break;
xjmp L55
L58:
.dbline 118
; case 1: //S2键按下,增加电阻的数字量
; data+=5;
mov R24,R10
subi R24,251 ; addi 5
mov R10,R24
.dbline 119
; break;
xjmp L55
L59:
.dbline 121
; case 2: //S3键按下,使电阻的数字量为零(阻值满量程)
; data=0;
clr R10
.dbline 122
; break;
xjmp L55
L60:
.dbline 124
; case 3: //S3键按下,使电阻的数字量为满(阻值清零,只剩下接触电阻)
; data=255;
ldi R24,255
mov R10,R24
.dbline 125
; break;
L54:
L55:
.dbline 127
; }
; MAX5478_writeB(0x50,0x13,data); //更新电阻
std y+0,R10
ldi R18,19
ldi R16,80
xcall _MAX5478_writeB
.dbline 128
; Delayms(5);
ldi R16,5
ldi R17,0
xcall _Delayms
.dbline 129
; }
L52:
.dbline 130
; }
L50:
.dbline 107
xjmp L49
X22:
.dbline -2
L48:
.dbline 0 ; func end
adiw R28,1
ret
.dbsym r data 10 c
.dbsym r i 12 c
.dbend
; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -