新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > AVR單片機讀PS2鼠標

        AVR單片機讀PS2鼠標

        作者: 時間:2016-11-24 來源:網絡 收藏
        如果該程序已驗證過的,用的是AVR系列單片機的IO口模擬PS2協議。

        #include

        本文引用地址:http://www.104case.com/article/201611/320643.htm

        #include
        #include "myh.h"
        //MOUSE
        //時鐘接CLK:5--INT0--PD2
        #define PINMCLK (PIND&BIT2)
        #define PRTMCLK_H {DDRD&=NBIT2;PORTD|=BIT2;}
        #define PRTMCLK_L {DDRD|=BIT2;PORTD&=NBIT2;}
        //數據接DAT:1--PC4
        #define PINMDAT (PINC&BIT4)
        #define PRTMDAT_H {DDRC&=NBIT4;PORTC|=BIT4;}
        #define PRTMDAT_L {DDRC|=BIT4;PORTC&=NBIT4;}

        //KEYBOARD

        #define PINKCLK (PIND&BIT3)
        #define PRTKCLK_H {DDRD&=NBIT3;PORTD|=BIT3;}
        #define PRTKCLK_L {DDRD|=BIT3;PORTD&=NBIT3;}
        //數據接DAT:1--PC4
        #define PINKDAT (PINC&BIT5)
        #define PRTKDAT_H {DDRC&=NBIT5;PORTC|=BIT5;}
        #define PRTKDAT_L {DDRC|=BIT5;PORTC&=NBIT5;}

        //sbit pclk=P3^2;
        //sbit pdat=P3^1;

        uchar wait;
        uchar mcnt=0;
        uchar kcnt=0;
        schar axes_x=0,axes_y=0;
        schar mbuf[4];
        uchar kbuf[4];

        void delay(uint t)//延時 t*10us
        {
        char i;
        for(;t>0;t--)
        for(i=10;i>0;i--);
        }

        uchar send2m(uchar dat)//高電平期間改變數據,下降沿發出去
        {
        uchar i,ack,intc,check=1;
        uint buf;

        //EX0=0;
        //IE0=0;
        intc=GICR;
        GICR&=0x3f; //不使能中斷
        buf=dat;
        for(i=0;i<8;i++)
        {
        check^=dat&0x01; //校驗,出現奇數個一該位為0。
        dat>>=1;
        }

        buf|=check<<8; //校驗位
        buf|=3<<9; //停止位,以及應答位

        // pclk=0;
        // pdat=0;
        PRTMCLK_L;
        PRTMDAT_L; //下接時鐘和數據
        delay(10);
        // pclk=1;//請求
        PRTMCLK_H;//釋放時鐘線
        for(i=0;i<11;i++)//發送8位數據
        {
        while(PINMCLK);//等待下降沿
        if(buf&0x01)
        PRTMDAT_H
        else
        PRTMDAT_L
        //pdat=buf&0x01;
        buf>>=1;
        //if(i==10)ack=pdat;//最后一位為輸入的應答
        if(i==10)ack=PINMDAT;
        //while(!pclk);
        while(!PINMCLK);//等待上升沿
        }
        PRTMDAT_H;
        //EX0=1;
        GICR=intc;
        return ack;
        }

        void chuli(void)
        {
        mcnt=0;
        axes_x+=(schar)mbuf[1];
        axes_y+=(schar)mbuf[2];
        }

        void display(uint number)//從0到F顯示
        {
        char i,n[4]={0}, //要顯示的四個數字
        num[16]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X27,0X7F,0X6F,
        0X77,0X7C,0X39,0X5E,0X79,0X71};//十六個數字的段碼
        n[0]=number>>12&0X0F;
        n[1]=number>>8 &0X0F;
        n[2]=number>>4 &0X0F;
        n[3]=number &0X0F;
        for(i=0;i<4;i++)
        {
        PORTD=~(0X80>>i);
        PORTB=num[n[i]];delay(500);
        PORTB=0x00; //顯示清空
        }
        }

        void port_init(void)
        {
        DDRB = 0xFF;//B用于顯示
        PORTB = 0xFF;
        DDRC = 0x0F;//PC4,PC5為輸入
        PORTC = 0x7F; //m103 output only
        DDRD = 0xF0; //INT0 INT1 為輸入
        PORTD = 0xFF;

        }

        #pragma interrupt_handler int0_isr:2
        void int0_isr(void)
        {
        //external interupt on INT0
        char i;
        uint buf;
        // EX0=0;
        PRTKCLK_L; //抑制鍵盤時鐘
        //PRTKDAT_L;
        //-while(1);
        buf=0;
        if(PINMDAT)
        {
        PORTC|=BIT0;
        delay(10);
        PORTC&=NBIT0;
        return; //啟始位為0
        }
        while(!PINMCLK); //等待啟始位結束
        for(i=0;i<10;i++)//8位數據+校驗+停止,LSB在前
        {
        while(PINMCLK);//下降沿接收數據
        if(PINMDAT)buf|=(1< while(!PINMCLK);
        }
        mbuf[mcnt]=buf&0xff;
        wait=50;
        mcnt++;
        if(mcnt==3)
        chuli();
        PRTKCLK_H; //允許鍵盤時鐘
        GIFR=0XC0; //向高兩位寫1,清中斷標志
        //IE0=0;
        }

        #pragma interrupt_handler int1_isr:3
        void int1_isr(void)
        {
        char i;
        uint buf;
        PRTMCLK_L; //抑制鼠標時鐘
        buf=0;
        if(PINKDAT)
        {
        PORTC|=BIT0;
        delay(10);
        PORTC&=NBIT0;
        return; //啟始位為0
        }
        while(!PINKCLK); //等待啟始位結束
        for(i=0;i<10;i++)//8位數據+校驗+停止,LSB在前
        {
        while(PINKCLK);//下降沿接收數據
        if(PINKDAT)buf|=(1< while(!PINKCLK);
        }
        kbuf[kcnt]=buf&0xff;
        kcnt=0;
        PRTMCLK_H; //允許鼠標時鐘
        GIFR=0XC0; //向高兩位寫1,清中斷標志
        }

        //call this routine to initialise all peripherals
        void init_devices(void)
        {
        //stop errant interrupts until set up
        CLI(); //disable all interrupts
        port_init();

        MCUCR = 0x0A;//1010,int0,int1 下降沿
        GICR = 0xC0; //int1,int0 enable
        TIMSK = 0x00; //timer interrupt sources
        SEI(); //re-enable interrupts
        //all peripherals are now initialised
        }


        void main()
        {
        uint dat;
        init_devices();

        send2m(0xff);
        delay(10);
        send2m(0xeb);

        while(1)
        {
        //dat=axes_x<<8|axes_y;
        dat=axes_x<<8|kbuf[0];
        display(dat);
        //display(kbuf[0]);
        if(wait)
        {
        wait--;
        if(wait==0)
        mcnt=0;
        }
        }
        }



        關鍵詞: AVR單片機PS2鼠

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 米易县| 湟中县| 民县| 赤水市| 沂南县| 德保县| 凤台县| 西贡区| 绥滨县| 丹寨县| 房产| 呼伦贝尔市| 旺苍县| 涡阳县| 郴州市| 临高县| 曲麻莱县| 瓦房店市| 海城市| 科尔| 双桥区| 阆中市| 洪江市| 哈尔滨市| 松原市| 宁河县| 信宜市| 北票市| 永善县| 于都县| 昌黎县| 喀什市| 仙桃市| 和田市| 盐城市| 丽江市| 澄城县| 奉贤区| 桃源县| 新龙县| 徐水县|