论坛风格切换切换到宽版
  • 4064阅读
  • 6回复

学习bascom:如何边运行程序边读键盘? [复制链接]

上一主题 下一主题
离线bg6qbv
 
发帖
5837
只看楼主 倒序阅读 0楼 发表于: 2008-07-13
边运行程序边读键盘,大家肯定说用中断了,但是问题来了,

触发中断一种是用检测引脚的电平(例如用int0/1),bascom的getkbd怎么怎么才能做到和int0/1关联?我量了一下kbd 4*4各按键引脚的电压,用二极管连接试验了,按键下去低电平不能触发int0/1,怎么处理这个问题呢?

另一种 我想到的就是用定时器中断,定时去读键盘。


大家一般是怎么做的????
离线小比尔/5
发帖
2582
只看该作者 1楼 发表于: 2008-07-13
直接放在主程序循环里……
while(1)
{
while(scankey()==0);
switch(scankey()){}
...
}
抱歉,用c写的
离线bg6qbv
发帖
5837
只看该作者 2楼 发表于: 2008-07-13
问题是主程序在不停的每隔1-2秒循环送lcd闪动的控制字,如果用while能做到实时响应吗?
离线fghlw
发帖
163
只看该作者 3楼 发表于: 2008-07-14
'
边运行程序边读键盘,大家肯定说用中断了,但是问题来了,
触发中断一种是用检测引脚的电平(例如用int0/1),bascom的getkbd怎么怎么才能做到和int0/1关联?我量了一下kbd 4*4各按键引脚的电压,用二极管连接试验了,按键下去低电平不能触发int0/1,怎么处理这个问题呢?
另一种 我想到的就是用定时器中断,定时去读键盘。
大家一般是怎么做的????
'
多输入或门 但响应时间就要测试了(中断响应因为多了这个要多几十us)
离线阳光999
发帖
52
只看该作者 4楼 发表于: 2008-07-15
我用过一有空就去检查按键是否有输入 效果还可以
  '------------------------------------------------------------------------------
  '名     称 : ex0031-1.bas
  '目     的 : 试验读取pcf8563时间日期,在lcd显示
  '按 键 说 明 : 按键sw13为 调整/正常 功能按钮,按键sw14,sw15,sw16,sw11为调整按钮←↓→↑
  '
  '目 标 芯 片 : mega16
  '试 验 环 境 : mega16_32%20kit.pdf(www.basicavr.com m16试验板)
  '编 译 环 境 : bascom-avr 1.11.8.1 demo
  '跳 线 设 置 : j42/j43 =12 j46=23,j16按晶体情况连接;没提到跳线均为空
  '熔 丝 说 明 : 外部晶振12m, jtag禁止
  '------------------------------------------------------------------------------

$regfile = "m16def.dat"
'$lib "mcsbyte.lbx"                             ' use the byte lib since we do not need longs
$crystal = 12000000
$baud = 19200
'declare used subs


declare sub settime(byval s1 as byte , byval m1 as byte , byval h1 as byte , byval d1 as byte , byval month1 as byte)
declare sub gettime()
declare sub time_start()
declare sub time_stop()
declare sub time_set()

'declare variables
dim tm(7) as byte at &h60                       '定义存放时间日期的数组
dim show_str(7) as string * 4                     '定义变量 tm()对应内容 调整时间时显示用
dim i as byte , temp as byte
dim j as byte
dim clock_state as bit                         '时钟的工作状态标志,0:工作;1 调整
'these are pointers to tm() for simple handling. 下面定义的几个变量对应tm(1-7)
dim s as byte at &h60 overlay
dim m as byte at &h61 overlay
dim h as byte at &h62 overlay
dim d as byte at &h63 overlay
dim w as byte at &h64 overlay
dim month as byte at &h65 overlay
dim year as byte at &h66 overlay

dim cent as integer

dim b as byte                               '键值
dim set_up as byte                             '调整时增加量 +时为2,-时为0,不操作时为1
dim set_addr as byte                           '要调整的寄存器地址 时间、日期的地址为02h到08h
dim byte_old_key as byte                         '记录旧键值


'configure the used port pin for i2c
config i2cdelay = 5                           ' default slow mode
config sda = portd.2
config scl = portd.3
config lcdpin = pin , db4 = portc.4 , db5 = portc.5 , db6 = portc.6 , db7 = portc.7 , e = portb.3 , rs = portb.4
config lcd = 16 * 2
config kbd = portc , delay = 50                   '键盘端口和消抖延时

clock_state = 0
set_up = 1
set_addr = 2
show_str(1) = "sec"
show_str(2) = "min"
show_str(3) = "hou"
show_str(4) = "day"
show_str(5) = "wek"
show_str(6) = "mon"
show_str(7) = "yer"

' not needed since the pins are in the right state
'i2cinit
'call settime(0 , 0 , 0 , 1 , 1 )                   '设置时间 1-1,00,


cls

do
  call gettime
  'since the values are stored in bcd format we can use hex() to display them

  h = h and &h3f
  m = m and &h7f
  s = s and &h7f
  cent = month and &h80
  if cent = 0 then
  cent = 1900
  else
  cent = 2000
  end if

  month = month and &h1f
  cent = cent + makedec(year)
  d = d and &h3f
  w = w and &h7


locate 1 , 1                               '指定lcd显示位置
lcd hex(h ) ; ":" ; hex(m) ; ":" ; hex(s)             'lcd显示
locate 2 , 1
lcd cent ; "-" ; hex(month) ; "-" ; hex(d) ; " w " ; hex(w)

b = getkbd()                               '读取键值

if b = 0 then                               '设置 工作/调整状态
  clock_state = not clock_state
  locate 1 , 10                             '指定lcd显示位置
  if clock_state = 1 then
    lcd "set "                             'lcd显示
  else
    lcd "       "
  end if
end if
locate 1 , 10                               '指定lcd显示位置

if clock_state = 1 then

  lcd "set " ; show_str(set_addr -1)               'lcd显示

  select case b
        case 4 : set_addr = set_addr - 1
        case 8 : set_up = 0
        case 9 : set_up = 2
        case 12 : set_addr = set_addr + 1
  end select
  if set_addr > 8 then
    set_addr = 8
  end if
  if set_addr < 2 then
    set_addr = 2
  end if
  if set_up <> 1 then
    call time_set()
    set_up = 1
  end if
  end if
  waitms 100
loop
end




sub gettime()

  'there are 2 ways to get the time. with low level i2c calls or with a high level call
  'first the high level call
  tm(1) = 2                               ' point to second register

  i2creceive &ha3 , tm(1) , 1 , 7                 ' write the second address and get 7 bytes back
  'i2creceive will first write 1 byte from tm(1) which is 2, and then will read 5 bytes and store it onto tm(1)-tm(5)


  'and optional with low level calls
' for i = 1 to 7
'   temp = i - 1
  '   i2cstart
  '   i2cwbyte &ha2                           'write addres of pcf8583
  '   i2cwbyte temp                           'select register
  '   i2cstart                               'repeated start
  '   i2cwbyte &ha3                           'write address for reading info
  '   i2crbyte tm(i) , nack                     'read data
  ' next
'i2cstop
end sub


sub settime(s1 as byte , m1 as byte , h1 as byte , d1 as byte , month1 as byte)
  'values are stored as bcd values so convert the values first

  tm(1) = makebcd(s1)                         'seconds
  tm(2) = makebcd(m1)                         'minutes
  tm(3) = makebcd(h1)                         'hours
  tm(4) = makebcd(d1)                         'days
  tm(5) = 5                               'week
  tm(6) = makebcd(month1) or &h80                 'cent=20
  tm(7) = makebcd(06)                         'year=06   默认06年

  call time_stop()

  i2cstart                                 'repeated start
  i2cwbyte &ha2                             'write mode
  i2cwbyte 2                               'select seconds register
  for i = 1 to 7
    i2cwbyte tm(i)
  next
  i2cstop

  call time_start()

end sub

sub time_stop()
  i2cstart                                 'generate start
  i2cwbyte &ha2                             'write address
  i2cwbyte 0                               'select control register
  i2cwbyte 32                               'clock stop
  i2cstop
end sub

sub time_start()

  i2cstart                                 'generate start
  i2cwbyte &ha2                             'write address
  i2cwbyte 0                               'select control register
  i2cwbyte 0                               'clock run
  i2cstop
end sub

sub time_set()

  i2cstart
  i2cwbyte &ha2                             'write addres of pcf8583
  i2cwbyte set_addr                           'select register
  i2cstart                                 'repeated start
  i2cwbyte &ha3                             'write address for reading info
  i2crbyte temp , nack                         'read data
  i2cstop
' print "t"
' print temp
'   if set_addr <> 6 then                       '处理星期部分
    temp = makedec(temp)
'   end if
' print temp
  temp = temp + set_up
  temp = temp - 1
' print temp
'   if set_addr <> 6 then
    temp = makebcd(temp)
'   end if
print temp
  call time_stop()

  i2cstart                                 'repeated start
  i2cwbyte &ha2                             'write mode
  i2cwbyte set_addr                           'select seconds register
  i2cwbyte temp
  i2cstop

  call time_start()

end sub
离线小比尔/5
发帖
2582
只看该作者 5楼 发表于: 2008-07-16
'
问题是主程序在不停的每隔1-2秒循环送lcd闪动的控制字,如果用while能做到实时响应吗?
'
把闪动的程序扔到中断里去运行...
离线小比尔/5
发帖
2582
只看该作者 6楼 发表于: 2008-07-16
以前做数字钟的时候我是这样处理的:
把走时的程序扔到中断,把键盘处理放在主循环里
中断定时分成很多时间片,整点报时、走时程序、扫描数码管在中断里分时处理
其实当时这么做,可能是因为想多了,不过后来想想,我搞了一个操作系统,哈哈哈~

void tmr0_svr() interrupt 1
{
     slot--;
     if(slot==0)
     {
           slot=maxslot;      /*如果时间片计满maxslot,说明5ms到,两个时隙,每10ms处理一次音乐,10ms处理一次显示 */

           if(slotbit){if(play) mplay();}            /* 分时处理,如果是下时隙,处理音乐 */
           else                                                /* 如果是上时隙,处理时间 */
           {
                 /* proctime线程:处理正常走时 */
                 tcount--;
                 if(tcount==0)      /* 如果1s时间到,则走时 */
                 {
                       tcount=100;
                       proctime();
                 }
           }
           slotbit=~slotbit;
           setbuff();
     }
     display(); posn--; if(posn==0){posn=8;}
}

void main()
{
     uchar func=0, keyin[6];      /* 功能, 直接数字输入缓冲区 */

     /* 初始化状态旗标、中断等 */
     tmod=0x02;th0=0x06;tl0=0x06;      //设置t0定时周期250us,8位自动重装
     tr0=1;et0=1;ea=1;                        //打开定时器0
     t2con=0x00;et2=1;pt2=1;pt0=0;
     mp=tone1;
     while(1)
     {
           uchar key;
           while(!chkkey());
           key=scankey();
           switch(key)
           {
           ......
           } /* switch */
           while(chkkey());
     }
}