这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » AVR 问AVR端口问题:

共2条 1/1 1 跳转至

AVR 问AVR端口问题:

院士
2006-09-17 18:14:16     打赏
AVR 问AVR端口问题:



关键词: 端口     问题    

院士
2006-12-22 22:43:00     打赏
2楼
问 读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,中断中读键值,两次相等才有效,就消抖动了。
另外该定时器也不是只这个功能,还可以提供定时信息等

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]