有pic写的矩阵键盘与数码管和单片机C语言的程序吗

有pic写的矩阵键盘与数码管和单片机C语言的程序吗,第1张

#include<pich>//矩阵键盘与数码管:当s1按下时6个显示全0,当s2按下时6个显示全1,当s16按下时6个显示全F

#define uchar unsigned char//宏定义

#define uint unsigned int

__CONFIG(0x3b31);//设置配置位

const uchar table[]={0x3f,0x06,0x5b,0x4f,//注意code是用在51单片机中的程序储存器中,const是一个常量,pic和51的单片机也可以共用的常量,但要写在前头

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71,0x20};//数码管数字表从0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,无显示

uchar key_num;//先定义一个变量为RB口低4位的检测

void delay(uint x);//声明

void init();

void scan();

void didi(uchar);

void disp();//在这里用的是静态显示全部管是一样的,所以不用加动态扫描时的变量

void main()

{

init();//调用初始化

while(1)//因为要不断地循环扫描键盘检测是否按下所以要进行死循环

{

scan();//调用键盘扫描程序

disp();//在调用键盘扫描的同时调用数码管

}

}

void delay(uint x)//延迟函数x表示毫秒

{

uint a,b;

for(a=x;a>0;a--)

for(b=110;b>0;b--);//嵌套

}

void init()

{

TRISB=0x0f;//因为RB口的高4位RB4-RB7为输出状态,低4位RB0-RB3为输入状态

TRISD=0;//因为RD接的是数码管段选设置全为输出状态

TRISE0=0;//设置RE0蜂鸣器为输出状态

TRISA=0;//设置数码管的位选为全输出状态

RE0=0;//先设置蜂鸣器为关闭不响

PORTD=0;//设置数码管的输出先全部关闭

PORTA=0xff;//设置数码管全部打开

}

void scan()//键盘扫描程序

{

/检测最后一行RB7是否有键按下/

uchar key_tem;//定义一个松手后才有变化的变量,可不加,但按下时数码管就会变化

PORTB=0x7f;//01111111先从最高位RB7开始,又因为低4位是输入状态,所以写什么都不影响,因为是不能输出的

key_num=PORTB;//将RB端口读回来

key_num=key_num&0x0f;//与00001111比较判断如果RB7这行的s13-s16是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//判定运算与之后如果不等0x0f,则有按键按下

{

delay(10);//去抖,再判断多一次

key_num=PORTB;//将RB端口读回来附给key_num

key_num=key_num&0x0f;//与00001111比较判断如果RB7这行的s13-s16是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//确定不等于0x0f,有键按下但未知是哪一列

{ //////////////////////////////////////////////////////松手后才有变化,可不加

key_tem=key_num;//将key_num也同时附给tem,这样就不影响松手后才能读到key_num的附回的值了,为作松手后才有变化

didi(1);//调用蜂鸣器

while(key_tem!=0x0f)//这个是松手检测,如果不加则按下的同时数码管就会有变化

{

key_tem=PORTB;//将RB端口读回来附给key_tem

key_tem=key_tem&0x0f;//与00001111比较

}//////////////////////////////////////////////////////松手后才有变化,可不加

key_num=key_num|0x70;//和01110000运算或比较,到这里0x7f先是和0x0f与运算但未知是哪一列,再和0x70或运算判断哪一列得出了具体的按键,再附给回key_num

}

}

/检测第三行RB6是否有键按下/

else

{

PORTB=0xbf;//10111111检测第三行RB6因为低4位是输入状态,所以写什么都不影响,因为是不能输出的

key_num=PORTB;//将RB端口读回来

key_num=key_num&0x0f;//与00001111比较判断如果RB6这行的s9-s12是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//判定运算与之后如果不等0x0f,则有按键按下

{

delay(10);//去抖,再判断多一次

key_num=PORTB;//将RB端口读回来附给key_num

key_num=key_num&0x0f;//与00001111比较判断如果RB6这行的s9-s12是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//确定不等于0x0f,有键按下但未知是哪一列

{ //////////////////////////////////////////////////////松手后才有变化,可不加

key_tem=key_num;//将key_num也同时附给tem,这样就不影响松手后才能读到key_num的附回的值了,为作松手后才有变化

didi(1);//调用蜂鸣器

while(key_tem!=0x0f)//这个是松手检测,如果不加则按下的同时数码管就会有变化

{

key_tem=PORTB;//将RB端口读回来附给key_tem

key_tem=key_tem&0x0f;//与00001111比较

}//////////////////////////////////////////////////////松手后才有变化,可不加

key_num=key_num|0xb0;//和10110000运算或比较,到这里0xbf先是和0x0f与运算但未知是哪一列,再和0xb0或运算判断哪一列得出了具体的按键,再附给回key_num

}

}

/在第一个else里继续第二个else检测第二行RB5是否有键按下/

else

{

PORTB=0xdf;//11011111检测第二行RB5因为低4位是输入状态,所以写什么都不影响,因为是不能输出的

key_num=PORTB;//将RB端口读回来

key_num=key_num&0x0f;//与00001111比较判断如果RB5这行的s5-s8是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//判定运算与之后如果不等0x0f,则有按键按下

{

delay(10);//去抖,再判断多一次

key_num=PORTB;//将RB端口读回来附给key_num

key_num=key_num&0x0f;//与00001111比较判断如果RB5这行的s5-s8是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//确定不等于0x0f,有键按下但未知是哪一列

{ //////////////////////////////////////////////////////松手后才有变化,可不加

key_tem=key_num;//将key_num也同时附给tem,这样就不影响松手后才能读到key_num的附回的值了,为作松手后才有变化

didi(1);//调用蜂鸣器

while(key_tem!=0x0f)//这个是松手检测,如果不加则按下的同时数码管就会有变化

{

key_tem=PORTB;//将RB端口读回来附给key_tem

key_tem=key_tem&0x0f;//与00001111比较

}//////////////////////////////////////////////////////松手后才有变化,可不加

key_num=key_num|0xd0;//和11010000运算或比较,到这里0xdf先是和0x0f与运算但未知是哪一列,再和0xd0或运算判断哪一列得出了具体的按键,再附给回key_num

}

}

/在第二个else里继续第三个else检测第一行RB4是否有键按下/

else

{

PORTB=0xef;//11101111检测第一行RB4因为低4位是输入状态,所以写什么都不影响,因为是不能输出的

key_num=PORTB;//将RB端口读回来

key_num=key_num&0x0f;//与00001111比较判断如果RB4这行的s1-s4是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//判定运算与之后如果不等0x0f,则有按键按下

{

delay(10);//去抖,再判断多一次

key_num=PORTB;//将RB端口读回来附给key_num

key_num=key_num&0x0f;//与00001111比较判断如果RB4这行的s1-s4是否有键按下,如果按下则RB低4位其中一个为0,再附给回key_num,这是判断哪一列

if(key_num!=0x0f)//确定不等于0x0f,有键按下但未知是哪一列

{ //////////////////////////////////////////////////////松手后才有变化,可不加

key_tem=key_num;//将key_num也同时附给tem,这样就不影响松手后才能读到key_num的附回的值了,为作松手后才有变化

didi(1);//调用蜂鸣器

while(key_tem!=0x0f)//这个是松手检测,如果不加则按下的同时数码管就会有变化

{

key_tem=PORTB;//将RB端口读回来附给key_tem

key_tem=key_tem&0x0f;//与00001111比较

}//////////////////////////////////////////////////////松手后才有变化,可不加

key_num=key_num|0xe0;//和11100000运算或比较,到这里0xef先是和0x0f与运算但未知是哪一列,再和0xe0或运算判断哪一列得出了具体的按键,再附给回key_num

}

}

}

}

}

}

void didi(uchar num)//蜂鸣器程序,num表示响多少声

{

uchar di_num;

for(di_num=num;di_num>0;di_num--)

{

RE0=1;//蜂鸣器响

delay(100);//响100ms

RE0=0;//蜂鸣器关闭

delay(50);//关闭50ms

}

}

void disp()//数码管

{

switch(key_num)//多选择语句,这前提要知道它的值再相应输出相对应的数

{

case 0xee:PORTD=table[0];break;//0xee(01110111)表示第一个键按下时,段选显示0字,位选在初始化中已打开

case 0xed:PORTD=table[1];break;

case 0xeb:PORTD=table[2];break;

case 0xe7:PORTD=table[3];break;

case 0xde:PORTD=table[4];break;

case 0xdd:PORTD=table[5];break;

case 0xd7:PORTD=table[6];break;

case 0xbe:PORTD=table[7];break;

case 0xbd:PORTD=table[8];break;

case 0xbb:PORTD=table[10];break;

case 0xb7:PORTD=table[11];break;

case 0x7e:PORTD=table[12];break;

case 0x7d:PORTD=table[13];break;

case 0x7b:PORTD=table[14];break;

case 0x77:PORTD=table[15];break;

}

}

邮箱不知!大体程序见下

;设定PORTA:4为输入端,PORTA,0,1,2,3,四个端口为输出端,点动按键放开按键后,计数并

;且点亮相应的灯(4位二进制显示),循环检测按键,闪动为亮05秒灭05秒再亮05秒灭05,

;然后进入按键检测,键按下时,端口为高电平,放开为低电平

;之前设置省略

BANKSEL TRISA

MOVLW 10H

MOVWF TRISA ; 设定PORTA:4为输入端,PORTA,0,2,3,四个端口为输出端

JIANCE_CHU

BANKSEL PORTA

CLRL PORTA ;输出端口清零

CLRF JISHU

JIANCE_G ;检测按键是否按下

BTFSS PORTA,4

GOTO $-1

CALL DELAY_10

BTFSS PORTA,4

GOTO JIANCE_G

JIANCE_D ;检测按键是否松开

BTFSC PORTA,4

GOTO $-1

CALL DELAY_10

BTFSC PORTA,4

GOTO JIANCE_D

INCF JISHU,1;计数器加1

MOVF JISHU,0

SUBLW 10H ;检测按键次数是否超过15次

BTFSS STATUS,Z

GOTO XIAN ; 没有超过,进入显示程序段

MOVLW 0FH ;超过,进入闪烁程序

MOVWF PORTA ;灯全亮

CALL DELAY_500 ;延时500毫秒

CLRF PORTA ; 灯全灭

CALL DELAY_500

MOVLW 0FH

MOVWF PORTA

CALL DELAY_500

CLRF PORTA

GOTO JIAN_CHU;进入按键检测初始化

XIAN ;显示程序段

MOVF JISHU,0

CALL BIAO;进入查表程序,返回二进制代码送显

MOVWF PORTA

GOTO JIANCE_G;返回按键检测,是否按下

DELAY_10 ;10毫秒延时

;略

DELAY_500 ;500毫秒延时

;略

BIAO ;查表程序

;略

END

我这里有一个机器上的程序,和你的情况是一样的,希望对你有所帮助

#include<pich>

#define sda RC1

#define scl RC0

const char table[]={0xde,0x44,0x7a,0x76,0xe4, //0,1,2,3,4

0xb6,0xbe,0x54,0xfe,0xf6, //5,6,7,8,9

0xf8}; //p

__CONFIG(0x09);

void start();

void stop();

void respons();

void sendresponse();

void write_byte(char dat); //写动作

void read_byte(); //读动作

void delay1(char x);

void xianshi();

void zuo(int nn);

void you(int nn);

void deng(int mk);

void niu0();

void niu1();

void niu2();

void niu3();

void niu4();

void niu5();

void niu6();

void niu7();

void niu8();

void niu9();

void shumafenpei();

bank2 int dengshuju,ji,read_shu;

bank2 int uu,uy,y,kk;

bank1 int di,di1,tingshan,yu;

bank1 int yi,er,san,si;

void main()

{

char a,b;

TRISA=0;

TRISB=0;

PORTA=0;

PORTB=0;

di=0;

di1=1;

tingshan=1;

yu=0;

dengshuju=1;

while(1)

{

//

TRISC =~(1<<0);

TRISC =~(1<<1); //置输出

sda=1; //数据预置高

ji=0; //--

scl=1; //时钟预置高

ji=0; //--

start();

write_byte(0xa0); //写入写的地址

respons();

write_byte(1); //写地址

respons();

start();

write_byte(0xa1); //写入读的地址和读动作

respons();

a=read_shu;

sendresponse();

b=read_shu;

stop();

PORTB=a;

//

shumafenpei();

xianshi();

if(di1==1)

{

if(di<5){RB0=0;}

else

{

RB0=0;

di=0;

di1=0;

}

di++;

}

}

}

void delay1(char x) //长延迟

{

char a,b;

for(a=x;a>0;a--)

for(b=110;b>0;b--);

}

void xianshi()

{

zuo(yi); //第一位数码

PORTA=0x00;

ji=0;//delay();

niu0();

ji=0;//delay();

PORTA=0x05;

ji=0;//delay();

niu5();

ji=0;//delay();

PORTA=0xff;

you(er); //第二位数码

PORTA=0x01;

ji=0;//delay();

niu1();

ji=0;//delay();

PORTA=0x06;

ji=0;//delay();

niu6();

ji=0;//delay();

zuo(san); //第三位数码

PORTA=0x02;

ji=0;//delay();

niu2();

ji=0;//delay();

PORTA=0x07;

ji=0;//delay();

niu7();

ji=0;//delay();

you(si); //第四位数码

PORTA=0x03;

ji=0;//delay();

niu3();

ji=0;//delay();

PORTA=0x08;

ji=0;//delay();

niu8();

ji=0;//delay();

deng(dengshuju); //指示灯

PORTA=0x04;

ji=0;//delay();

niu4();

ji=0;//delay();

PORTA=0xff;

PORTA=0x09;

ji=0;//delay();

niu9();

ji=0;//delay();

if(tingshan==1)

{

yu++;

if(yu<40)dengshuju=dengshuju|0x30; //0011 0000

if(yu>40&&yu<80)dengshuju=dengshuju&0xcf; //1100 1111

if(yu>80)yu=0;

}

if((dengshuju&0x10)&&(tingshan!=1))

{

dengshuju=dengshuju&0xf0;

dengshuju=dengshuju|0x01;

}

}

void zuo(int nn)

{

int mm=table[nn];

int i;

for(i=0;i<8;i++)

{

RB7=0; //时钟信号预先置零

RA0=(mm&0x01); //取最边沿数值

RB7=1;

mm=mm>>1;

}

}

void you(int nn)

{

int nu,nzuo,nyou,i;

nu=table[nn]; //取数

nzuo=(nu&0xaa); //抽1、3、5、7位

nyou=(nu&0x55); //抽2、4、6、8位

nzuo=nzuo>>1; //1、3、5、7变2、4、6、8

nyou=nyou<<1; //2、4、6、8变1、3、5、7

nu=(nzuo|nyou); //合数,赋值给nu

for(i=0;i<8;i++)

{

RB7=0; //时钟信号预先置零

RA0=(nu&0x01); //取最边沿数值

RB7=1;

nu=nu>>1;

}

}

void deng(int mk)

{

int i;

for(i=0;i<8;i++)

{

RB7=0; //时钟信号预先置零

RA0=(mk&0x01); //取最边沿数值

RB7=1;

mk=mk>>1;

}

}

void niu0()

{

int y0;

kk=dengshuju&0x0f;

if(RC2!=0)

{

uu=uu&0xfe; //1111 1110按钮标志位置零

}

y0=uu&0x01; //抽取按钮标志位的真假

if(RC2==0)

{

if((y0==0)&&((dengshuju&0x20)||tingshan==1))

{

di1=1;

switch(kk)

{

case 0x01:kk=0x08;break;

case 0x02:kk=0x01;break;

case 0x04:kk=0x02;break;

case 0x08:kk=0x04;break;

}

dengshuju=dengshuju&0xf0; //清除旧记录

dengshuju=dengshuju|kk; //注入新记录

}

uu=uu|0x01;

}

}

void niu1()

{

if(RC2!=0)

{

uy=uy&0xfd; //1111 1101按钮标志位置零

}

y=uy&0x02; //0000 0010抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uy=uy|0x02;

}

}

void niu2()

{

if(RC2!=0)

{

uy=uy&0xfe; //1011 1111按钮标志位置零

}

y=uy&0x01; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uy=uy|0x01;

}

}

void niu3()

{

if(RC2!=0)

{

uu=uu&0xf7; //1011 1111按钮标志位置零

}

y=uu&0x08; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uu=uu|0x08;

}

}

void niu4()

{

kk=dengshuju&0x30; //0x00 0000取灯(单循/自动)状态

if(RC2!=0)

{

uu=uu&0xfd; //1111 1101按钮标志位置零

}

y=uu&0x02; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0)

{

di1=1;

tingshan=0;

switch(kk)

{

case 0x00:kk=0x20;break;

case 0x20:kk=0x10;break;

case 0x10:kk=0x20;break;

case 0x30:kk=0x20;break;

}

dengshuju=dengshuju&0xcf; //1011 1111清除旧记录

dengshuju=dengshuju|kk; //注入新记录

}

uu=uu|0x02;

}

}

void niu5()

{

kk=dengshuju&0x40; //0x00 0000取灯(单循/自动)状态

if(RC2!=0)

{

uu=uu&0xfb; //1111 1011按钮标志位置零

}

y=uu&0x04; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0)

{

di1=1;

if(kk==0)kk=0x40;

else kk=0;

dengshuju=dengshuju&0xbf; //1011 1111清除旧记录

dengshuju=dengshuju|kk; //注入新记录

}

uu=uu|0x04;

}

}

void niu6()

{

kk=dengshuju&0x80; //x000 0000取灯(圆面/平面)状态

if(RC2!=0)

{

uu=uu&0xdf; //1101 1111按钮标志位置零

}

y=uu&0x20; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0)

{

di1=1;

if(kk==0)kk=0x80;

else kk=0;

dengshuju=dengshuju&0x7f; //0111 1111清除旧记录

dengshuju=dengshuju|kk; //注入新记录

}

uu=uu|0x20;

}

}

void niu7()

{

if(RC2!=0)

{

uu=uu&0xbf; //1011 1111按钮标志位置零

}

y=uu&0x40; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uu=uu|0x40;

}

}

void niu8()

{

if(RC2!=0)

{

uu=uu&0xef; //1011 1111按钮标志位置零

}

y=uu&0x10; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uu=uu|0x10;

}

}

void niu9()

{

if(RC2!=0)

{

uu=uu&0x7f; //1011 1111按钮标志位置零

}

y=uu&0x80; //抽取按钮标志位的真假

if(RC2==0)

{

if(y==0){di1=1;}

uu=uu|0x80;

}

}

void shumafenpei()

{

int jishu,juanzhi,yayin,tingliu,kk,yu;

jishu=read_shu;

juanzhi=3344;

yayin=5566;

tingliu=7788;

kk=dengshuju&0x0f;

switch(kk)

{

case 0x01:yu=jishu; break;

case 0x02:yu=tingliu; break;

case 0x04:yu=yayin; break;

case 0x08:yu=juanzhi; break;

}

yi=yu/1000;

yu=yu%1000;

er=yu/100;

yu=yu%100;

san=yu/10;

yu=yu%10;

si=yu;

}

//

//IIC通讯程序

void start() //开始信号(时钟高,数据由高变低)

{ //

TRISC=~(1<<1); //

sda=1; //数据高,准备启动下沿信号

ji=0; //--

scl=1; //时钟高

ji=0; //--

sda=0; //数据拉低,开始信号到位

ji=0; //--

}

void stop() //停止信号(时钟高,数据由低变高)

{ //

TRISC =~(1<<1); //置输出??

sda=0; //数据低,准备停止上沿信号

ji=0; //--

scl=1; //时钟高,

ji=0; //

sda=1; //数据拉高,停止信号到位

ji=0; //--

}

void respons() //应答检测

{

char i;

TRISC=(1<<1); //设置为输入

scl=1; //时钟高

ji=0; //--

while((sda==1)&&(i<250)) //如果数据高并且没循环完毕,i自增

i++;

scl=0; //时钟高

ji=0; //--

}

void sendresponse() //发送应答

{

TRISC=~(1<<1); //置输出

sda=0; //数据低

ji=0; //--

scl=1; //时钟高

ji=0; //--

scl=0; //时钟低,

ji=0; //--

sda=1; //数据高

}

void write_byte(char dat) //写动作

{

char i,temp,d;

TRISC =~(1<<1); //置输出

temp=dat; //函数被赋值转交temp

for(i=0;i<8;i++) //开始传输八位数据

{

if((temp&0x80)==0x80)//如果最左一位是1

d=1;

else

d=0;

scl=0; //时钟低

ji=0; //--

sda=d; //数据被赋值

ji=0; //--

scl=1; //接收完,时钟回复高

ji=0; //--

temp=temp<<1; //最左传输完,再左移一位

}

scl=0; //结束,时钟低

ji=0; //--

sda=1; //数据高

ji=0; //--

}

void read_byte() //读动作

{

char i,k;

TRISC =(1<<1); //设置为输入

scl=0; //时钟低

ji=0; //--

sda=1; //释放数据总线

ji=0; //--

for(i=0;i<8;i++)

{

scl=1; //时钟高

ji=0; //--

k=(k<<1)|sda; //k先腾出位,再灌数据,再刷新k

scl=0; //时钟低

ji=0; //--

}

read_shu=k; //函数给出读出数据

}

PIC12C508A,DataSheet说,1,000,000次。

PIC10F200, DataSheet说, 100,000次。

调试程序绰绰有余啊。

您在没有下载该芯片资料之前,就敢下刀子划拉了啊?厉害!

哈哈哈哈。估计你看的也是没有注释的。你可以用仿真器跟踪程序的执行过程。烧写程序很简单的。找个烧写器,也叫编程器,选择芯片型号,load你生成的代码。擦除,查空,编程,校验,一般都是这4个步骤。至于程序的对错。。。。。。那得看你要实现甚么功能了

以上就是关于有pic写的矩阵键盘与数码管和单片机C语言的程序吗全部的内容,包括:有pic写的矩阵键盘与数码管和单片机C语言的程序吗、pic程序求解。汇编语句怎么写、帮忙写个PIC单片机小程序,编译成功立即给分等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9392353.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存