共2条
1/1 1 跳转至页
问
读PINA寄存器的时候,读到的是端口的实际电平还是寄存器的锁存值?那如果读PORTA呢?
我做键盘程序,C口0-3送出,4-7读入,可以直接送了后改方向寄存器DDRA就读入吗?
请指教! 答 1: rePINA是实际电平,PORTA是锁存值
可以读,加nop 答 2: to ne5532大哥,拜托你看书仔细一点嘛!书上写得很清楚啊!pin只是一个访问物理管脚的地址阿!读出来的数据是管脚上的电平值!port是锁存寄存器值,你要写端口就先送数到port,综上所述,读就读pin,写就写port.
请指教!
btw ne5532你给我的粉丝不好吃,不如以前哈! 答 3: 邓小平同志告诉我们:实践是检验真理的唯一标准!!没有硬件,当然要问了!!! 答 4: 找一个AVR的书来看看;---叫你去那里下ping是管脚;
port是锁存器;
你到www.sl.com上找找,他会提供AVR的一些资料;
在老古的网上还有pdf的书籍下载
任何一本AVR的书都提到了oing 和port的区别;
对了;
写好了键盘的东西给我一份;
我现在要做一个键盘,想偷点懒====呵呵
地址
shishaojun2003@yahoo.com.cn
如果到我的东西出来了你还没有搞定的话,我也可以给你;
但我是用c的 答 5: 我用汇编写完了,大家提提建议,硬件是SL仿真器。value里面是最后的结果,用C口做键盘,涉及到的寄存器你可以压栈保存。
新手上路,请大家多多指教。
程序在studio3.5上通过,没有上硬件调试过。
.include"8515def.inc"
.org $0000
rjmp start
;Produced By JHBCD@SWUST
;E-mail:protel99sesp6@sohu.com
.def temp=r16 ;临时数据存储
.def keya=r17 ;读入的列键值a
.def keyb=r18 ;读入的列键值b
.def keyy=r19 ;扫描数据送出
.def kvalue=r20 ;键值查询计数器
.def count=r24 ;列值查询计数器
.def value=r21 ;最终取得的键值
;****************************************
.org $0010
start:
ldi temp,$02
out sph,temp
ldi temp,$5F
out spl,temp
ldi keyy,$08
ldi count,$00
ldi value,$00
keysweep:
;键盘扫描一次完成
;将其他程序加在这里
ldi temp,$FF
out ddrc,temp ;C口数据方向定义
out portc,keyy ;扫描开始
rjmp read ;读取
keyret:
lsr keyy ;!!!换列!!!《读取键值后返回点》
adiw count,$04 ;计数器自加
ldi temp,$10 ;看是否扫完了四列
cp temp,count
brne keysweep
ldi keyy,$08 ;重新初始化
ldi count,$00
rjmp keysweep ;!!!大循环!!!
;****************************************
read: ;键盘读取程序段
rcall delay ;等待键盘稳定
ldi temp,$00
out ddrc,temp ;重新定义C口方向
in keya,pinc ;读入电平
rcall delay
rcall delay
rcall delay ;去抖动,3毫秒
in keyb,pinc ;再次读取键值
cp keya,keyb ;两次的键值比较
brne read ;不等就再次读取
cp keya,keyy ;看有没有键按下
breq keyret ;没有键按下,去扫下一列
ldi kvalue,$04 ;键值读取程序段
keycount:
clc ;抗干扰
lsl keya ;右移,找到按下的键
dec kvalue ;自减键值查询计数器
brcs final ;找到键后,送出
rjmp keycount ;循环
final: add kvalue,count;计算键值
;dec kvalue ;修正值-1
mov value,kvalue;结果正式送出
rjmp keysweep ;等待下一次扫描
;****************************************
delay: ;1ms延时子程序
push temp ;现场保护
push r31
lp1: ldi temp,$01;04
lp2: ldi r31,$01;FF
lp3: wdr
wdr
wdr
wdr
wdr ;5T延时核程序
dec r31
brne lp3
dec temp
brne lp2
pop r31
pop temp ;现场恢复
ret
;**************************************** 答 6: 键盘程序最终版本。昨天的程序有问题,今天在硬件上调试通过。
这也是我写的第一个比较大的AVR程序,请大家指教:
;********************************************************
;在键盘上输入一个数,在LED上显示出数值
;硬件环境AT90S8515双龙AVR仿真器
;2003年7月
;********************************************************
.include"8515def.inc"
.org $0000
rjmp start
;Produced By JHBCD@SWUST
;E-mail:protel99sesp6@sohu.com
.def temp=r16
.def sweep=r17
.def invalue=r18
.def value=r19
.def basicvalue=r20
.def counter=r21
;********************************************************
.org $0010
ledcode:
;a段在最高位码表
;.db $FC,$60,$DA,$F2,$66,$B6,$BE,$EO
;.db $FE,$F6,$EE,$3E,$9C,$7A,$9E,$8E
;a段在最低位码表
.db $3F,$06,$5B,$4F,$66,$6D,$7D,$07
.db $7F,$6F,$77,$7C,$39,$5E,$79,$71
;********************************************************
start:
ldi temp,$02
out sph,temp
ldi temp,$5F
out spl,temp
ldi temp,$0F
out ddrc,temp
ldi value,$00
sweepin:
ldi sweep,0B11110111 ;扫描初始化
ldi basicvalue,$00 ;扫描初始化
next:
out portc,sweep
rcall display
;********************************************************
;两次读入键盘,将有键按下的列送去读值
emc:
rcall delay
rcall delay
rcall delay
rcall delay
rcall delay
in invalue,pinc
mov temp,invalue
sub temp,sweep ;检查本列是否有键按下
breq sweepmove ;没有键按下,扫描下移行
rcall delay
rcall delay
rcall delay
rcall delay
rcall delay
in temp,pinc
sub temp,invalue ;两次读入电磁兼容
brne emc
rcall read ;读取键值自程序
rjmp sweepin
;*******************************************************
;1ms延时子程序
delay:
ldi temp,$10
lp1: ldi r31,$FF
lp2: wdr
wdr
wdr
wdr
wdr ;5T延时核程序
dec r31
brne lp2
dec temp
brne lp1
ret
;*******************************************************
;换列扫描
sweepmove:
sec
ror sweep
ldi temp,$04
add basicvalue,temp
ldi temp,$FF
sub temp,sweep
brne next
rjmp sweepin
;*******************************************************
;当前列所按下键的值读取
read:
com invalue
ldi counter,$03
cycle:
clc
rol invalue
brcs finalvalue
dec counter
rjmp cycle
finalvalue:
add basicvalue,counter
mov value,basicvalue
ret
;*******************************************************
;显示程序
display:
ldi temp,$FF
out ddrb,temp
out ddrd,temp
ldi temp,$FE
out portd,temp
ldi zh,high(ledcode*2)
ldi zl,low(ledcode*2)
add zl,value
lpm
out portb,r0
ret
;******************************************************* 答 7: 不好!用了这么多delay,mcu还能干些什么? 答 8: 那 用什么好啊? 答 9: 自己想想想明白了比别人说一大堆不一定说得明白的话有用
CPU老是在等delay……还有多少时间处理其它事?还能高速运算吗? 答 10: 如果MCU真的没事做,可以睡觉啊,哈哈!!!这样比较省电嘛,发热也自然就少喽。
结论:没事的时候多睡会儿大有好处!! 答 11: 如果可以加硬件,我就做成外中断触发。 答 12: 仅量不用ms级延时子程序!ms级延时子程序开机初始化时用之倒也简而便。用了那么多ms级延时子程序的软件仅能作实验用吧!说明AVR MCU某些功能倒是例子常用手段。
用定时中断吧!
儆一个糸统时标,高效。 答 13: 我的C语言的先反转法,写得不好,凑合着看吧,欢迎批评
键盘编码 3*4
//0xf6(a) 0xee(up) 0xde(b)
//0xf5(left) 0xed(run) 0xdd(right)
//0xf3(del) 0xeb(down) reset
//0xbe(SA) 0xbd(SB) 0xbb(Load)
//状态编码
//0b10000000->a;
//0b10000001->b;
//0b01000000->up;
//0b01000001->left;
//0b01000010->right;
//0b01000011->down;
//0b00100000->run;
//0b00010000->Load;
//0b00000100->del;
//0b00001000->SA;
//0b00001001->SB;
void keyboard()
{
unsigned char temp1,temp2;
GIMSK=0;
delay(32);
temp1=PINC;
DDRC=0b10000111;
PORTC=0b11111000;
temp2=PINC;
temp2=(~temp2)|temp1;
switch(temp2)
{
case 0xf6:
state=0b10000000;
break;
case 0xde:
state=0b10000001;
break;
case 0xee:
state=0b01000000;
break;
case 0xf5:
state=0b01000001;
break;
case 0xdd:
state=0b01000010;
break;
case 0xeb:
{state=0b01000011;
break;}
case 0xbb:
{state=0b00010000;
break;}
case 0xf3:
{state=0b00000100;
break;}
case 0xbe:
{state=0b00001000;
break;}
case 0xbd:
{state=0b00001001;
break;}
case 0xed:
{state=0b00100000;
break;}
default:
state=0;
}
DDRC=0b11111000;
PORTC=0b10000111;
DDRD&=0b11111011;
} 答 14: to: NE5532to: NE5532
我開始學單片機時也曾像你那樣想過.不過程序寫出來.實際是不可行的.
后來是我門的一個高工提示我.如果想省時間和程序空間,最好是設標志位.
1: 令 t=0
2: 掃描鍵盤.有鍵按下---->t=1?
a: t=1 跳轉出來---> end
b: t=0 鍵處理---->t=1
3: 沒鍵按下---->t=0----> end
當然這只是思路.
哈... 答 15: 好,谢谢,我试试看。 答 16: 用定时器做时标如10ms,中断中读键值,两次相等才有效,就消抖动了。
另外该定时器也不是只这个功能,还可以提供定时信息等
我做键盘程序,C口0-3送出,4-7读入,可以直接送了后改方向寄存器DDRA就读入吗?
请指教! 答 1: rePINA是实际电平,PORTA是锁存值
可以读,加nop 答 2: to ne5532大哥,拜托你看书仔细一点嘛!书上写得很清楚啊!pin只是一个访问物理管脚的地址阿!读出来的数据是管脚上的电平值!port是锁存寄存器值,你要写端口就先送数到port,综上所述,读就读pin,写就写port.
请指教!
btw ne5532你给我的粉丝不好吃,不如以前哈! 答 3: 邓小平同志告诉我们:实践是检验真理的唯一标准!!没有硬件,当然要问了!!! 答 4: 找一个AVR的书来看看;---叫你去那里下ping是管脚;
port是锁存器;
你到www.sl.com上找找,他会提供AVR的一些资料;
在老古的网上还有pdf的书籍下载
任何一本AVR的书都提到了oing 和port的区别;
对了;
写好了键盘的东西给我一份;
我现在要做一个键盘,想偷点懒====呵呵
地址
shishaojun2003@yahoo.com.cn
如果到我的东西出来了你还没有搞定的话,我也可以给你;
但我是用c的 答 5: 我用汇编写完了,大家提提建议,硬件是SL仿真器。value里面是最后的结果,用C口做键盘,涉及到的寄存器你可以压栈保存。
新手上路,请大家多多指教。
程序在studio3.5上通过,没有上硬件调试过。
.include"8515def.inc"
.org $0000
rjmp start
;Produced By JHBCD@SWUST
;E-mail:protel99sesp6@sohu.com
.def temp=r16 ;临时数据存储
.def keya=r17 ;读入的列键值a
.def keyb=r18 ;读入的列键值b
.def keyy=r19 ;扫描数据送出
.def kvalue=r20 ;键值查询计数器
.def count=r24 ;列值查询计数器
.def value=r21 ;最终取得的键值
;****************************************
.org $0010
start:
ldi temp,$02
out sph,temp
ldi temp,$5F
out spl,temp
ldi keyy,$08
ldi count,$00
ldi value,$00
keysweep:
;键盘扫描一次完成
;将其他程序加在这里
ldi temp,$FF
out ddrc,temp ;C口数据方向定义
out portc,keyy ;扫描开始
rjmp read ;读取
keyret:
lsr keyy ;!!!换列!!!《读取键值后返回点》
adiw count,$04 ;计数器自加
ldi temp,$10 ;看是否扫完了四列
cp temp,count
brne keysweep
ldi keyy,$08 ;重新初始化
ldi count,$00
rjmp keysweep ;!!!大循环!!!
;****************************************
read: ;键盘读取程序段
rcall delay ;等待键盘稳定
ldi temp,$00
out ddrc,temp ;重新定义C口方向
in keya,pinc ;读入电平
rcall delay
rcall delay
rcall delay ;去抖动,3毫秒
in keyb,pinc ;再次读取键值
cp keya,keyb ;两次的键值比较
brne read ;不等就再次读取
cp keya,keyy ;看有没有键按下
breq keyret ;没有键按下,去扫下一列
ldi kvalue,$04 ;键值读取程序段
keycount:
clc ;抗干扰
lsl keya ;右移,找到按下的键
dec kvalue ;自减键值查询计数器
brcs final ;找到键后,送出
rjmp keycount ;循环
final: add kvalue,count;计算键值
;dec kvalue ;修正值-1
mov value,kvalue;结果正式送出
rjmp keysweep ;等待下一次扫描
;****************************************
delay: ;1ms延时子程序
push temp ;现场保护
push r31
lp1: ldi temp,$01;04
lp2: ldi r31,$01;FF
lp3: wdr
wdr
wdr
wdr
wdr ;5T延时核程序
dec r31
brne lp3
dec temp
brne lp2
pop r31
pop temp ;现场恢复
ret
;**************************************** 答 6: 键盘程序最终版本。昨天的程序有问题,今天在硬件上调试通过。
这也是我写的第一个比较大的AVR程序,请大家指教:
;********************************************************
;在键盘上输入一个数,在LED上显示出数值
;硬件环境AT90S8515双龙AVR仿真器
;2003年7月
;********************************************************
.include"8515def.inc"
.org $0000
rjmp start
;Produced By JHBCD@SWUST
;E-mail:protel99sesp6@sohu.com
.def temp=r16
.def sweep=r17
.def invalue=r18
.def value=r19
.def basicvalue=r20
.def counter=r21
;********************************************************
.org $0010
ledcode:
;a段在最高位码表
;.db $FC,$60,$DA,$F2,$66,$B6,$BE,$EO
;.db $FE,$F6,$EE,$3E,$9C,$7A,$9E,$8E
;a段在最低位码表
.db $3F,$06,$5B,$4F,$66,$6D,$7D,$07
.db $7F,$6F,$77,$7C,$39,$5E,$79,$71
;********************************************************
start:
ldi temp,$02
out sph,temp
ldi temp,$5F
out spl,temp
ldi temp,$0F
out ddrc,temp
ldi value,$00
sweepin:
ldi sweep,0B11110111 ;扫描初始化
ldi basicvalue,$00 ;扫描初始化
next:
out portc,sweep
rcall display
;********************************************************
;两次读入键盘,将有键按下的列送去读值
emc:
rcall delay
rcall delay
rcall delay
rcall delay
rcall delay
in invalue,pinc
mov temp,invalue
sub temp,sweep ;检查本列是否有键按下
breq sweepmove ;没有键按下,扫描下移行
rcall delay
rcall delay
rcall delay
rcall delay
rcall delay
in temp,pinc
sub temp,invalue ;两次读入电磁兼容
brne emc
rcall read ;读取键值自程序
rjmp sweepin
;*******************************************************
;1ms延时子程序
delay:
ldi temp,$10
lp1: ldi r31,$FF
lp2: wdr
wdr
wdr
wdr
wdr ;5T延时核程序
dec r31
brne lp2
dec temp
brne lp1
ret
;*******************************************************
;换列扫描
sweepmove:
sec
ror sweep
ldi temp,$04
add basicvalue,temp
ldi temp,$FF
sub temp,sweep
brne next
rjmp sweepin
;*******************************************************
;当前列所按下键的值读取
read:
com invalue
ldi counter,$03
cycle:
clc
rol invalue
brcs finalvalue
dec counter
rjmp cycle
finalvalue:
add basicvalue,counter
mov value,basicvalue
ret
;*******************************************************
;显示程序
display:
ldi temp,$FF
out ddrb,temp
out ddrd,temp
ldi temp,$FE
out portd,temp
ldi zh,high(ledcode*2)
ldi zl,low(ledcode*2)
add zl,value
lpm
out portb,r0
ret
;******************************************************* 答 7: 不好!用了这么多delay,mcu还能干些什么? 答 8: 那 用什么好啊? 答 9: 自己想想想明白了比别人说一大堆不一定说得明白的话有用
CPU老是在等delay……还有多少时间处理其它事?还能高速运算吗? 答 10: 如果MCU真的没事做,可以睡觉啊,哈哈!!!这样比较省电嘛,发热也自然就少喽。
结论:没事的时候多睡会儿大有好处!! 答 11: 如果可以加硬件,我就做成外中断触发。 答 12: 仅量不用ms级延时子程序!ms级延时子程序开机初始化时用之倒也简而便。用了那么多ms级延时子程序的软件仅能作实验用吧!说明AVR MCU某些功能倒是例子常用手段。
用定时中断吧!
儆一个糸统时标,高效。 答 13: 我的C语言的先反转法,写得不好,凑合着看吧,欢迎批评
键盘编码 3*4
//0xf6(a) 0xee(up) 0xde(b)
//0xf5(left) 0xed(run) 0xdd(right)
//0xf3(del) 0xeb(down) reset
//0xbe(SA) 0xbd(SB) 0xbb(Load)
//状态编码
//0b10000000->a;
//0b10000001->b;
//0b01000000->up;
//0b01000001->left;
//0b01000010->right;
//0b01000011->down;
//0b00100000->run;
//0b00010000->Load;
//0b00000100->del;
//0b00001000->SA;
//0b00001001->SB;
void keyboard()
{
unsigned char temp1,temp2;
GIMSK=0;
delay(32);
temp1=PINC;
DDRC=0b10000111;
PORTC=0b11111000;
temp2=PINC;
temp2=(~temp2)|temp1;
switch(temp2)
{
case 0xf6:
state=0b10000000;
break;
case 0xde:
state=0b10000001;
break;
case 0xee:
state=0b01000000;
break;
case 0xf5:
state=0b01000001;
break;
case 0xdd:
state=0b01000010;
break;
case 0xeb:
{state=0b01000011;
break;}
case 0xbb:
{state=0b00010000;
break;}
case 0xf3:
{state=0b00000100;
break;}
case 0xbe:
{state=0b00001000;
break;}
case 0xbd:
{state=0b00001001;
break;}
case 0xed:
{state=0b00100000;
break;}
default:
state=0;
}
DDRC=0b11111000;
PORTC=0b10000111;
DDRD&=0b11111011;
} 答 14: to: NE5532to: NE5532
我開始學單片機時也曾像你那樣想過.不過程序寫出來.實際是不可行的.
后來是我門的一個高工提示我.如果想省時間和程序空間,最好是設標志位.
1: 令 t=0
2: 掃描鍵盤.有鍵按下---->t=1?
a: t=1 跳轉出來---> end
b: t=0 鍵處理---->t=1
3: 沒鍵按下---->t=0----> end
當然這只是思路.
哈... 答 15: 好,谢谢,我试试看。 答 16: 用定时器做时标如10ms,中断中读键值,两次相等才有效,就消抖动了。
另外该定时器也不是只这个功能,还可以提供定时信息等
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |