发 帖  
原厂入驻New

如何建立AVRPS/2硬件中断控制程序?

41 PC键盘 数据
分享
建立操作PC键盘的示例程序(硬件中断读取PS/2接收到的数据)

0
2020-11-5 06:40:51   评论 分享淘帖 邀请回答
1个回答
  /*01010101010101010101010101010101010101010101010101010101010101010101
  ----------------------------------------------------------------------
  版本更新记录:
  ----------------------------------------------------------------------
  实验内容:
  按PC键盘,观察单片机读到的数据,使用PA/PB口的LED做指示。
  ----------------------------------------------------------------------
  硬件连接:
  将PA/PB口的LED指示灯使能开关切换到“ON”状态
  将PC键盘插入PS2接口,将PD3与PS2.SDA连接,将PD4与PS2.SCK连接
  ----------------------------------------------------------------------
  注意事项:
  (1)若有加载库函数,请将光盘根目录下的“库函数”下的“ICC_H”文件夹拷到D盘
  (2)请详细阅读“使用必读”及相关资料。
  ----------------------------------------------------------------------
  10101010101010101010101010101010101010101010101010101010101010101010*/
  #include
  #include “D:\ICC_H\CmmICC.H”
  #include “D:\ICC_H\PS2.H”
  #define PRESS_DATA_DDR DDRA
  #define PRESS_DATA_PORT PORTA
  #define SHIFT_DATA_DDR DDRB
  #define SHIFT_DATA_PORT PORTB
  #define SET_SDA sbi(PORTD,4)
  #define CLR_SDA cbi(PORTD,4)
  #define GET_SDA gbi(PIND,4)
  #define OUT_SDA sbi(DDRD,4)
  #define IN_SDA cbi(DDRD,4)
  #define SET_SCK sbi(PORTD,3)
  #define CLR_SCK cbi(PORTD,3)
  #define GET_SCK gbi(PIND,3)
  #define OUT_SCK sbi(DDRD,3)
  #define IN_SCK cbi(DDRD,3)
  bool rcvF = 0; //是否收到字符标志
  uint8 keyVal; //键值
  /*--------------------------------------------------------------------
  函数名称:PS/2
  函数功能:
  注意事项:
  提示说明:
  输 入:
  返 回:
  --------------------------------------------------------------------*/
  #pragma interrupt_handler int1_isr:3
  void int1_isr(void)
  {
  static uint8 rcvBits = 0; //接收次数,中断次数
  if((rcvBits》0) && (rcvBits《9))
  {
  keyVal=keyVal》》1; //数据是LSB格式
  //IN_SDA; //当有对键盘有属性设置时,注意输入输出切换
  //DELAY();
  if(GET_SDA)
  keyVal=keyVal|0x80;
  }
  rcvBits++;
  while(!GET_SCK); //等待PS/2CLK拉高
  if(rcvBits》10)
  {
  rcvBits=0; //接收11次表示接收完一帧数据
  rcvF=1; //标识有字符已经输入
  }
  }
  /*--------------------------------------------------------------------
  函数名称:PS/2
  函数功能:
  注意事项:
  提示说明:
  输 入:
  返 回:
  --------------------------------------------------------------------*/
  void keyHandle(uint8 val)
  {
  uint8 i;
  static bool isUp=0; //按键释放动作标志
  static bool shift=0; //shift键按下标志
  rcvF = 0;
  PRESS_DATA_PORT = val; //状态指示
  if(!isUp)
  {
  switch(val)
  {
  case 0xF0 : // a relase action
  isUp = 1;
  break;
  case 0x12 : // Left shift
  shift = 1;
  break;
  case 0x59 : // Right shift
  shift = 1;
  break;
  default:
  if(!shift) // If shift not pressed
  {
  /*
  for(i=0; unshifted[0]!=val && unshifted[0]; i++)
  ;
  上述写法较为灵活,但KEIL非UNIXC标准,不能采用该写法
  */
  for(i=0; unshifted[0]!=val && i《59; i++)
  ;
  if(unshifted[0] == val)
  ; //状态指示
  }
  else // If shift pressed
  {
  /*
  for(i=0; unshifted[0]!=val && unshifted[0]; i++)
  ;
  上述写法较为灵活,但KEIL非UNIXC标准,不能采用该写法
  */
  for(i=0; shifted[0]!=val && i《59; i++)
  ;
  if(shifted[0] == val)
  SHIFT_DATA_PORT = val;//状态指示
  }
  }
  }
  else
  {
  isUp=0;
  switch(val)
  {
  case 0x12 : // Left SHIFT
  shift = 0;
  break;
  case 0x59 : // Right SHIFT
  shift = 0;
  break;
  }
  }
  }
  /*--------------------------------------------------------------------
  函数名称:PS/2
  函数功能:
  注意事项:
  提示说明:
  输 入:
  返 回:
  --------------------------------------------------------------------*/
  void int1_init()
  {
  IN_SCK; // set SCK_DDR (PD3/INT1) as input
  SET_SCK; // set SCK_PORT as high level,avoid triggering
  MCUCR |= 0b11110011; // set PD3/INT1 as low level active
  GICR |= 0b10000000; // enable global interrupt
  SEI(); // enable external interrupt
  }
  /*--------------------------------------------------------------------
  函数名称:PS/2
  函数功能:
  注意事项:
  提示说明:
  输 入:
  返 回:
  --------------------------------------------------------------------*/
  void main(void)
  {
  PRESS_DATA_DDR = 0XFF;
  SHIFT_DATA_DDR = 0XFF;
  IN_SDA;
  int1_init();
  while(1)
  {
  if(rcvF)
  keyHandle(keyVal);
  }
  }
2020-11-5 15:53:10 评论

举报

只有小组成员才能发言,加入小组>>

325个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表