miaoweiseu 发表于 2009-3-9 17:27:06

请教马老师关于mega16做ps/2接口的问题!

马老师您好,我用Mega16做一个键盘鼠标接口,功能只是将扫描码传给上位机,同时将上位机发送的命令值发送给ps/2设备。单独的向串口发送扫描码和串口向ps/2设备发送命令都成功的,问题是当发送命令给键盘的时候键盘的动作是对的,可是返回值却不对,而且一旦有发送命令给键盘以后的按键扫描码也都不对了,代码如下,请您指教,谢谢 !

外部中断监控ps/2的时钟线
USART采用中断接收数据

#include <iom16v.h>
#include <macros.h>

#define BAUD9600
#define BARR(7372800/(16*BAUD)-1)
#define Getdata() (PIND&0X10)

volatile unsigned char ps0revdata=0;
volatile unsigned char bitcount=0;
volatile char flag=0;

//UART初始化函数
void UART_init( void )
{
      UBRRH = (unsigned char)(BARR>>8);
      UBRRL = (unsigned char)BARR;
      UCSRB = (1<<RXCIE)|(1<<TXEN)|(1<<RXEN);//使能接收中断,使能接收,使能发送
      UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//设置侦格式,异步,8位数据,一个停止位,无倍速      
}

//UART发送数据
void uart_transmit(unsigned char data)
{
      while(!(UCSRA&(1<<UDRE)));
         
      UDR = data;

}


void pulldown_clk(void)//拉低时钟线
{
   DDRD|=(1<<3);
   PORTD&=~(1<<3);
}

void pulldown_data(void){//拉低数据线
   DDRD|=(1<<4);
   PORTD&=~(1<<4);
   }
   
   
void Release_clk(void)//释放时钟线
{
   DDRD&=~(1<<3);
   //PORTD|=(1<<3);
}

void delay_1us(void)//延时程序
{
      
}

void delay_nus(unsigned char n)
{
   unsigned int i=0;
   for(i=0;i<n;i++)
   delay_1us();
}

//外部中断1的中断服务程序,用于获得ps2设备扫描码
#pragma interrupt_handler int1_scr:3
void int1_scr(void)
{
    flag=0;
      bitcount++;
      if(bitcount==1)
      {
                if(Getdata()==1)
                {
                        bitcount = 0;
                }
      }

      else if((bitcount>=2)&&(bitcount<=9))
      {
               
                ps0revdata>>=1;
               
                if(Getdata()==0)
                {
                        ps0revdata|=0x00;
                }
                else
                {
                        ps0revdata|=0x80;
                }
            
      }
      else if(bitcount == 11)
      {
                flag = 1;
                bitcount = 0;
            uart_transmit(ps0revdata);
            ps0revdata=0;
      }
}

//向ps2设备发送数据
void send_ps2data(unsigned char sendps2data)
{
    unsigned char sendbit_cnt= 0x00;
    unsigned char paritysum = 0x00;
      unsigned char data=0x00;
      unsigned char temp=0x00;
      temp=sendps2data;
    CLI(); //disable all interrupts
   
      pulldown_clk();//将时钟线拉低并保持100 us
    delay_nus(100);
    Release_clk();//释放时钟线
         
      pulldown_data();//拉低数据线
      //Release_data();//释放数据线
         
      while(((PIND>>3)&0x01))//等待时钟线变低
                      ;
                           
    //发送数据
    for(sendbit_cnt=0;sendbit_cnt<8;sendbit_cnt++)
   {
      
      data=temp&0x01;
      if(data==1)
          PORTD|=(1<<4);
      else
          PORTD&=~(1<<4);
      paritysum+=data;//计算校验位
                temp>>=1;//待发数据右移一位
               
      while(!((PIND>>3)&0x01))   
                      ;//等待时钟线变高
         
                while(((PIND>>3)&0x01))//等待时钟线变低
                      ;
   }
      
   //发送校验位
   //while(ps2_clkstatus); //等待时钟线变低         
   if(paritysum==1)
         PORTD&=~(1<<4);
   else
          PORTD|=(1<<4);
   while(!(PIND>>3)&0x01)   
                ;//等待时钟线变高
   while((PIND>>3)&0x01)   
                ;//等待时钟线变低
      
         //发送停止位
   PORTD|=(1<<4);
   while(!(PIND>>3)&0x01)   
                ;//等待时钟线变高
         while((PIND>>3)&0x01)   
                ;//等待时钟线变低
         
      //接收ACK
      DDRD&=0xe7;
    SEI();
}

//UART接收数据中断
#pragma interrupt_handler USART_RXC:12
void USART_RXC(void)
{   
    unsigned char temp;
      temp=UDR;
    send_ps2data(temp);
      temp=0;
}

void main()
{   unsigned char i;
    CLI();
    UART_init();
         MCUCR = 0x08;
         GICR= 0x80;
      SEI();
         
      for(i=0;i<60000;i++)//延时
      ;
      while(1){
         
      }
}

machao 发表于 2009-3-15 22:56:38

你把硬件和要求都给我,我可以帮你全部设计好。不过需要付研发费用的。

dxjk 发表于 2009-4-17 21:25:55

请问马老师怎样联系,我有这方面的需求dxjk@163.com
页: [1]
查看完整版本: 请教马老师关于mega16做ps/2接口的问题!