数码之家

 找回密码
 立即注册
搜索
查看: 698|回复: 40

[C51] 请大佬帮忙改矩阵键盘排序

[复制链接]
发表于 2024-4-17 09:01:59 | 显示全部楼层 |阅读模式
1000家元
本帖最后由 shangh 于 2024-4-17 09:06 编辑

做一台Q表想用市售成品4x4的矩阵键盘,但是原作者的键盘排序与市售成品不一样,不会单片机自己改不了,大佬们能否帮忙改?万分感谢!


IO口需保持原样只改键盘排序,改成下图中右下市售成品的排序。
单片机是STC12LE5A602S

IMG_4790.JPG


原代码


/*************************************
Q表驱动程序 V3.1
xjw01 于莆田 2010.10
**************************************/
//====================================
#define uchar unsigned char
#define uint  unsigned int
#define ulong  unsigned long
#include <reg52.h>

void delay(uint loop) { uint i; for(i=0;i<loop;i++); } //延时函数
void delay2(uint k){ for(;k>0;k--) delay(10000); } //长延时,k=100大约对应1秒

//========================AD转换=============================
sfr P1ASF = 0x9D; //将P1置为模拟口寄存器(使能),各位中为1的有效
sfr ADC_CONTR = 0xBC; //A/D转换控制寄存器
sfr ADC_res   = 0xBD; //A/D转换结果寄存器
sfr ADC_resl  = 0xBE; //A/D转换结果寄存器

void set_channel(char channel){
P1ASF = 1<<channel;
ADC_CONTR = channel+128; //最高位是电源开关,低3位通道选择
delay(1); //首次打开电源应延迟,使输入稳定
}
uint get_AD2(){
ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
return ADC_res*4 + ADC_resl;
}

/*
uchar get_AD(){
ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
while( !(ADC_CONTR & 0x10) );  //等待A/D转换结束(ADC_FLAG==0)
ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
return ADC_res;
}
*/
//============================EEPROW偏程=========================
sfr IAP_data  = 0xC2;
sfr IAP_addrH = 0xC3;
sfr IAP_addrL = 0xC4;
sfr IAP_cmd   = 0xC5;
sfr IAP_trig  = 0xC6;
sfr IAP_contr = 0xC7;
/********************
写字节时,可以将原有数据中的1改为0,无法将0改为1,只能使用擦除命令将0改为1
应注意,擦除命令会将整个扇区擦除
*********************/
uchar readEEP(uint k){ //读取
IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
IAP_cmd = 1;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A;  //先送5A
IAP_trig = 0xA5;  //先送5A再送A5立即触发
return IAP_data;
}
void writeEEP(uint k, uchar da){ //写入
IAP_data = da;    //传入数据
IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
IAP_cmd = 2;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A;  //先送5A
IAP_trig = 0xA5;  //先送5A再送A5立即触发
}
void eraseEEP(uint k){ //擦除
IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
IAP_cmd = 3;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
IAP_trig = 0x5A;  //先送5A
IAP_trig = 0xA5;  //先送5A再送A5立即触发
}

#define Nda 23
xdata struct Ida{
int bas;    //比值基数
int z[Nda]; //激励电压表
int C,C2;   //主调电容的电大值与最小值,单位0.1pF
int jz[14]; //125等分非线性改正表,jz[0]存放初始温度下的零点电压(初次非线性桥正时的零点电压)而不存0值
} cs;

void cs_RW(char rw){
uchar i,*p = &cs;
if(rw){
  eraseEEP(0);
  for(i=0;i<sizeof(cs);i++) writeEEP(i,p);
}else{
  for(i=0;i<sizeof(cs);i++) p=readEEP(i);
}
}



//=============================DDS部分========================
#define fMax 12500000
xdata ulong feq=600000;
xdata uchar fstep=100;

sbit FSYNC=P2^1; //DDS使能
sbit SCLK=P2^2;  //DDS串行时钟
sbit SDATA=P2^3; //DDS串行数据

void DDS_W16(uint d){ //写32比特数据到DDS
  uchar i;
  SCLK = SDATA = FSYNC=1;  delay(3000);
  FSYNC=0; //使能(或同步)打开,数据开始传送
  delay(5);
  for(i=0;i<16;i++){
    SDATA = d>>15; delay(1);
        SCLK = 0;           delay(1);
        SCLK = 1;           delay(1);
        d<<=1;
  }
  
  FSYNC=1; delay(1);
  SCLK=0;  delay(1);
}

void DDS_init(void){
  DDS_W16(0x2100); //B28=1(28位连续写频置位),选择频率0相位0,RESET=1
  //DDS_W16(0x2500); //B28=1(28位连续写频置位),选择频率0相位1,RESET=1
  //DDS_W16(0x2900); //B28=1(28位连续写频置位),选择频率1相位0,RESET=1
  //DDS_W16(0x2D00); //B28=1(28位连续写频置位),选择频率1相位1,RESET=1
  //当RESET置位后,开始初始化频率和相位
  DDS_W16(0x4000);        //写频率0寄存器的低字节LSB
  DDS_W16(0x4000);        //写频率0寄存器的高字节MSB
  DDS_W16(0x8000);        //写频率1寄存器的低字节LSB
  DDS_W16(0x8000);        //写频率1寄存器的高字节MSB
  DDS_W16(0xC000);        //写相位0
  DDS_W16(0xF000);        //写相位1
  DDS_W16(0x2000);        //28位连续,选择频率0,相位0,RESET=0        
}

void DDS_f(){ //设置频率
  ulong m;
  uint mL,mH;
  if( feq > fMax ) feq = fMax;
  m = feq*10 + feq*11/16 + feq*12/256 + feq*12/256/16 + feq*6/65536; // f* 268435456/ 25000000
  mL = m, mH = m>>14;          //分离出低字节和高字节(各14bit有效)
  mL = (mL & 0x3FFF) + 0x4000; //补上前导01
  mH = (mH & 0x3FFF) + 0x4000; //补上前导01
  DDS_W16(0x2000);        DDS_W16(mL);  DDS_W16(mH); //连续28bit写频,RESET=0时所设频率被应用
}


/**********
字形编码图
   32
   -
64| | 128
   -  16
1| | 8
   _. 4
   2
**********/
uchar code zk[20]={235,136,179,186,216,122,123,168,251,250}; //字库

uchar disp[6]={168,251,250}; char cx=-1; //显示缓存,cx光标位置
sfr P1M1=0x91; //P1端口设置寄存器
sfr P1M0=0x92; //P1端口设置寄存器
sfr P0M1=0x93; //P0端口设置寄存器
sfr P0M0=0x94; //P0端口设置寄存器
sfr P2M1=0x95; //P2端口设置寄存器
sfr P2M0=0x96; //P2端口设置寄存器
sfr P3M1=0xB1; //P3端口设置寄存器
sfr P3M0=0xB2; //P3端口设置寄存器

sbit ds3=P2^4; //数码管扫描口
sbit ds2=P2^5; //数码管扫描口
sbit ds1=P2^6; //数码管扫描口
sbit ds0=P2^7; //数码管扫描口
sbit kx0=P3^4; //键盘扫描口
sbit kx1=P3^5; //键盘扫描口
sbit kx2=P3^6; //键盘扫描口
sbit kx3=P3^7; //键盘扫描口

sbit K0=P3^3;  //调零开关端口(输出)
sbit KP=P3^2;  //电源管理
sbit spk=P2^0; //蜂鸣器



//功能程序开始

xdata uchar menu=1,menuF=0,menu2=0;

void cls(){ char i; for(i=0;i<6;i++) disp=0; } //清屏
void showDig(long f){ //显示数字
uchar i;
cls();
for(i=0;i<6;i++) { disp=zk[f%10], f/=10; if(!f) break; }
}


uchar tms=0,ts=0,tm=0,th=0; ////tms为5ms计数器
uchar tmX=0; //无操作时间(自动关机使用)

void timerInter1(void) interrupt 3 {//T1中断
  TH1=0xa8; TL1+=0x11;
  tms++;
  if(tms==100){
    tms = 0, ts++; //秒跳变
    if(ts==60){
      ts=0, tm++,tmX++;  //分钟跳变
      if(tm==60) tm=0, th++;
      if(th==24) th=0;
          if(tmX==8) KP = 0; //自动关机
        }
  }
}


void timerInter(void) interrupt 1 {//T0中断
}


xdata int V0=0,V1=0,V10=0; //V0调零电压,V1检波电压
int code lineV[14]={0,1,2,3,4,5,10,15,20,25,50,75,100,125}; //娇正输出表(线性表)
int jiaozheng(long v){ //输入已调零的电压值
char i,b;
int a;
if(v<=0) return 0;
for(i=1;i<14;i++) if(v<cs.jz) break;
if(i==14) i=13;
//温漂改正
b = (V0-cs.jz[0])*7/10; //零点漂移量的70%
if(v<170) v += v*b/170;
else     v += b;
//矫正
if(i) a = cs.jz[i-1]; else a = 0;
return lineV[i-1]*10 + (lineV-lineV[i-1])*10*(v-cs.jz[i-1])/(cs.jz-cs.jz[i-1]);
}


uint Qlc(int f, ulong v){ //Q值计算,f单位千赫,非线性v矫正后的电压
  xdata int a = cs.z[Nda-1];
  xdata char i;
  i = f/500, f%=500;
  if(i<Nda-1)  a = cs.z + f*(cs.z[i+1]-cs.z)/500;
  return (v*cs.bas + a/2)/a;
}

void showQ(){ //显示Q
  if(V1>=1023) { disp[0]=disp[1]=disp[2]=disp[3]=128; return; }
  showDig( Qlc(feq/1000,jiaozheng(V1-V0)) );
  disp[1] += 4;
}

void showF(){ //显示频率
  if(ts%4==0){
    showDig(feq%10000);
    disp[3] = 115;
        if(!disp[1]) disp[1]=zk[0];
        if(!disp[2]) disp[2]=zk[0];
  }else{
    showDig(feq/1000);
        if(feq>=10000000) disp[3]+=4;
  }
}
void zeroOff(){ //读取调零值
  spk=1; //关闭蜂鸣器,防音频干扰
  K0=1;  delay2(50); //调零开关置位
  V0=get_AD2();      //读取调零电压
  K0=0;  delay2(50); //调零开关复位
}

xdata ulong fm=0; //中心谐振点
int Q3db=0,C0=0; //3dB Q值,C0分布电容
long Lx = 10000,Cz=5000; //Lx被电感的电感量(单位0.01uH),Cz主调电容值(单位0.1pF)
int readV(ulong f){ feq=f; DDS_f(); delay(60000); return jiaozheng(get_AD2()-V0); } //置频率并读取谐振电压,返回矫正后的电压
void autoF(int maxQ,char N){ //自动查找谐振点,N扫频点数(实扫频2N+1点),通常N=50足够,N<maxQ/2
char i,k; //循环变量
xdata long bc=feq/maxQ;  //扫描步长,建议maxQ=5000设计
char im=0,an=0; int vm=0,qm; //极点变量
xdata int va,vb,v3db;   //偏频计算的变量
xdata long pf,pf1,pf2;  //偏频计算的变量

spk=1; //关闭蜂鸣器,防音频干扰
delay2(100);//等待1秒

//开始扫频,查找极点
fm = feq;
for(k=0;k<2;k++){ //分两次查找,第一次粗调,第二次细调
   an=0, vm=0; //an溢出计数器
   for(i=-N;i<=N;i++){
     feq=fm+i*bc; DDS_f();      //设置频率
     delay(4000); V1=get_AD2(); //读电压
     if(vm<V1) im=i,vm=V1;      //记录最大值
         if(V1>=1023) an++;
   }
   im += an/2, fm+=im*bc; //极值位置
   N=10, bc/=N;
}

vm=jiaozheng(vm-V0), v3db = vm*17/24, qm=Qlc(fm/1000,vm);
//已找到谐振点,下面进一频做3dB分析
pf = fm*5/qm; //带通半宽度
va = readV(fm+pf/2); if(va<v3db) qm*=5,pf/=5; //量程判断
pf1 = pf, pf2 = -pf;
va = readV(fm+pf);      //右频偏1
vb = readV(fm+pf*9/10); //右频偏2
if(vb!=va) pf1 -= (pf/10)*(v3db-va)/(vb-va); //精确右偏频点
va = readV(fm-pf);      //左频偏1
vb = readV(fm-pf*9/10); //左频偏2
if(vb!=va)  pf2 += (pf/10)*(v3db-va)/(vb-va); //精确左偏频点

//谐振点及3dB
fm = fm+(pf2+pf1)/2; //谐振频率
if(pf1>pf2) Q3db = fm*10/(pf1-pf2); else Q3db=0; //计算3dB Q值
if(!Lx) Lx = 2.53303e19/fm/fm/cs.C; //电感量计算,单位0.01uH
Cz = 2.53303e19/fm/fm/Lx;        //谐振总电容,单位0.1pF
if(Q3db>qm) C0 = Cz*(Q3db-qm)/Q3db; else C0=0; //1l是1的长整型
feq = fm; DDS_f();
}

main(){
uchar i=0,j=0,kn=0,key=0,act=1;
uchar dispN=0; //显示扫描索引
uchar spkN=0;  //蜂鸣器发声时长

//定时器T0设置,用于信号发生器
TCON=0, TMOD=0x12; //将T0置为自动重装定时器,T1置为定时器
TH1=0xA8, TL1=0x11;
TR1=1;  //T1开始计数
TR0=0;  //T0暂停计数
ET1=1;  //T1开中断
ET0=1;  //T1开中断
EA=1;   //开总中断
PT0=1;  //设置优先级


set_channel(0); //设置AD转换通道
P2M0 = 0xF0;    //P2.4567置为推勉输出
P1M1 = 0x03;    //P1.01置为高阻抗
P3M0 = 0x0C;    //P3.23置为推勉输出口

delay2(50); //等待电路的电压平稳
zeroOff();  //调零
DDS_init(); DDS_f(); //DDS初始化
cs_RW(0); //读取比值基数(调零时已做开机延时,确保电压上升到可读取EEPROW)

while(1){
  V10-=(V10+5)/10; V10+=get_AD2(); V1=(V10+5)/10;  //取检波电压(数字滤波)
  //显示disp
  dispN=(++dispN)%4; //扫描器移动
  ds0=ds1=ds2=ds3=0;
  if(dispN==0) ds0=1;
  if(dispN==1) ds1=1;
  if(dispN==2) ds2=1;
  if(dispN==3) ds3=1;
  if(dispN==cx && tms>100) P0=255; //光标闪烁
  else P0=~disp[dispN]; //显示
  //扫描键盘
  for(i=0,key=255;i<16;i++){
        kx0=kx1=kx2=kx3=1;
        switch(i%4){ //X线置0
          case 0: kx0=0; break;
          case 1: kx1=0; break;
          case 2: kx2=0; break;
          case 3: kx3=0;
        }
        if(!(P1 & 1<<i/4+4 )) { key=i; if(kn<255) kn++; break; } //有键按下
  }
  if(i==16) kn=0; //无键按下
  //键盘响应
  if(kn==20) spkN=50,tmX=0; else key=255;   //当按下一定时间后,key才有效,否则无效。spkN发声时长设置
  if(spkN) spkN--, spk=0; else spk=1; //键盘发声
  //菜单系统
  if(key==15) menu=0,menu2=0;
  if(key==12) { if(menuF) menu=menuF, menuF=0; else menuF=menu, menu=255; key=255; } //频率显示键
  if(menuF){ //编辑频率
    if(key<10 ) feq = feq*10+key; //设置频率,有数字键按下则进入编辑状态
        if(key==10) feq = 0;          //清除
        if(key==11) feq *= 1000;      //整千赫输入
        if(key<15) DDS_f();
    showF(); //显示
  }

  if(menu==0){ //显示菜单
    int Vbat;
    set_channel(1); //设置AD转换通道
        delay(20); Vbat = get_AD2(); //读取电池电压
    set_channel(0); //设置AD转换通道
        Vbat = Vbat*14/29;
    showDig(Vbat);
        disp[2]+=4;
        disp[3]=2;
        if(key<15) { menu=key;  continue; }
  }
  if(menu==1){ //显示Q
    if(key<=4) menu2 = key;
    if(key==13) { feq += fstep;  DDS_f(); }    //频率微调
    if(key==14) { feq -= fstep;  DDS_f(); }    //频率微调
        if(key==5)  { feq = 1000000; DDS_f(); }    //设置频率为中波段频率的中心
        if(key==6)  { feq = 3000000; DDS_f(); }    //设置频率为3MHz频率
        if(key==7)  { autoF(200,100); } //宽范围自动粗调谐
           if(key==8)  { fstep=20;  }
           if(key==9)  { fstep=100; }
        if(key==11) { autoF(5000,50); } //窄范围自动细调谐
    if(key==10) { zeroOff(); }   //调零
    if(menu2==0) { if(tms%10==0) showQ();      } //显示Q
        if(menu2==1) { showDig(Q3db); disp[1]+=4;  } //显示3dB法Q值
        if(menu2==2) { showDig(Cz);   disp[1]+=4;  } //显示主调电容
        if(menu2==3) { showDig(C0);   disp[1]+=4;  } //显示分布电容
        if(menu2==4) { //显示电感量
          if(Lx<9999)       { showDig(Lx);    disp[2]+=4; }
          else if(Lx<99999) { showDig(Lx/10); disp[1]+=4; }
          else              { showDig(Lx/100); }
        }
  }
  if(menu==14){ Lx=0; autoF(5000,50); menu=1; key=255; } //电感量测量
  if(menu==2){ //显压显示
   if(key>=0&&key<10) menu2=key;
   if(key==10) zeroOff(); //强制调零
   if(menu2==0) { if(tms%10==0) showDig(jiaozheng(V1-V0)); } //显示矫正后的电压
   if(menu2==1) { if(tms%10==0) showDig(V0); } //显示调零电压
   if(menu2==2) { if(tms%10==0) showDig(V1); } //显示检波电压
  }
  if(menu==3){ //编辑比值基数
    if(key==14) menu2=0;
    if(key==13) menu2=1;
        if(menu2==0){ //设置变压器的比值(例如比值为56,应输入560)
      if(key<10) cs.bas = cs.bas*10+key; //修改
      if(key==10) cs.bas = 0; //清零
          if(key==11) cs_RW(1); //保存
          showDig(cs.bas);
         }
        if(menu2==1){ //设置主调电容的最大容量
      if(key<10) cs.C = cs.C*10+key; //修改
      if(key==10) cs.C = 0; //清零
          if(key==11) cs_RW(1); //保存
          showDig(cs.C);
         }
  }
  if(menu==4){ //编辑激励电压
    //频点选择
    if(key==14&&menu2>0) menu2--;
    if(key==13&&menu2<Nda-1) menu2++;
    //手动修改
    if(key<10) cs.z[menu2] = cs.z[menu2]*10+key; //手动修改
    if(key==10) cs.z[menu2] = 0; //清零
        if(key==0 && cs.z[menu2]==0){ //已清零再输入0则全部清0
          for(i=0;i<Nda;i++) cs.z=0;
        }
        if(key==11){ //保存
      spk=1; //关闭蜂鸣器,防音频干扰
          for(i=0;i<Nda;i++){ //自动检查,如果数据为空则自动测量
            if(cs.z>0&&cs.z<255) continue;
        if(i==0) feq = 300; else feq = i*500;
            feq*=1000; DDS_f();
        delay2(5); V1=get_AD2(); //读电压
            cs.z = jiaozheng(V1-V0);
          }
      cs_RW(1);
        }
        showDig(cs.z[menu2]*10+(menu2/2)%10);
        disp[1]+=4;        if(menu2%2) disp[0]+=4;
  }
  if(menu==5){ //非线性校正数据编辑
    //插值点选择
    if(key==14&&menu2>0) menu2--;
    if(key==13&&menu2<13) menu2++;
    if(key<10) cs.jz[menu2] = cs.jz[menu2]*10+key; //编辑
    if(key==10) cs.jz[menu2] = 0; //清零
        if(key==11) cs_RW(1); //保存
        if(ts%2) { showDig(lineV[menu2]); disp[3]=207; }//显示等分定标电压值
        else showDig(cs.jz[menu2]);        //显示未桥正的电压值(已调零)
  }
  delay(4000);
}//while end
}



发表于 2024-4-17 09:29:59 | 显示全部楼层
本帖最后由 digitking 于 2024-4-17 10:15 编辑

看三楼和四楼

紫薯紫薯紫薯紫薯补丁
回复

使用道具 举报

发表于 2024-4-17 09:33:25 | 显示全部楼层
最傻的改法,定义一个Old_Key变量,扫描键盘的Key值付给Old_key。使用前,增加一个Old_Key 到Key的转换。

打赏

参与人数 1家元 +9 收起 理由
shangh + 9 熱心會員

查看全部打赏

回复

使用道具 举报

发表于 2024-4-17 09:51:27 | 显示全部楼层
本帖最后由 digitking 于 2024-4-17 10:13 编辑

改这段,加上一些键位转换也可以
  1.   //扫描键盘
  2.   for(i=0,key=255;i<16;i++){
  3.         kx0=kx1=kx2=kx3=1;
  4.         switch(i%4){ //X线置0
  5.           case 0: kx0=0; break;
  6.           case 1: kx1=0; break;
  7.           case 2: kx2=0; break;
  8.           case 3: kx3=0;
  9.         }
  10.         if(!(P1 & 1<<i/4+4 )) { key=i; if(kn<255) kn++; break; } //有键按下
  11.   }
复制代码


就在key=i;这里,首先加个方法:
  1. uchar key_T[16]={
  2. 1,2,3,10,
  3. 4,5,6,11,
  4. 7,8,9,12,
  5. 13,0,14,15
  6. };

  7. uchar trans_keys(uchar i){
  8.     return key_T[i];
  9. }
复制代码


把key=i; 改成
  1. key=trans_keys(i);
复制代码

打赏

参与人数 1家元 +30 收起 理由
shangh + 30 熱心會員

查看全部打赏

回复

使用道具 举报

发表于 2024-4-17 09:53:51 | 显示全部楼层
本帖最后由 china007lsh 于 2024-4-17 09:57 编辑

感觉在 “//键盘响应”  的前面加上转换就行了
swich (key)
case 0: key=1;break;
case 1: key=2;break;
case 2: key=3;break;
case 3: key=10;break;
……
……
回复

使用道具 举报

 楼主| 发表于 2024-4-17 10:28:02 | 显示全部楼层
digitking 发表于 2024-4-17 09:51
改这段,加上一些键位转换也可以

不好意思本人愚钝,单片机都没入门,截了图是不是像图中那样改



代码.JPG

回复

使用道具 举报

发表于 2024-4-17 10:57:56 | 显示全部楼层
digitking 发表于 2024-4-17 09:51
改这段,加上一些键位转换也可以

最好改法
回复

使用道具 举报

发表于 2024-4-17 11:02:24 | 显示全部楼层
本帖最后由 digitking 于 2024-4-17 11:03 编辑
shangh 发表于 2024-4-17 10:28
不好意思本人愚钝,单片机都没入门,截了图是不是像图中那样改

不是这样,看四楼,改这行:
  1. if(!(P1 & 1<<i/4+4 )) { key=i; if(kn<255) kn++; break; } //有键按下
复制代码
改成:

  1. if(!(P1 & 1<<i/4+4 )) { key=trans_keys(i); if(kn<255) kn++; break; } //有键按下
复制代码


回复

使用道具 举报

 楼主| 发表于 2024-4-17 11:22:39 | 显示全部楼层
本帖最后由 shangh 于 2024-4-17 11:28 编辑
digitking 发表于 2024-4-17 11:02
不是这样,看四楼,改这行:
改成:

只改这一条代码就可以了?

你重新编辑后的这段代码加到哪里呢?

代码.JPG
回复

使用道具 举报

发表于 2024-4-17 14:11:54 | 显示全部楼层
uchar key_T[16]={
1,2,3,10,
4,5,6,11,
7,8,9,12,
13,0,14,15
};

开头增加前面这个数组定义

下面程序中
//扫描键盘
  for(i=0,key=255;i<16;i++){
        kx0=kx1=kx2=kx3=1;
        switch(i%4){ //X线置0
          case 0: kx0=0; break;
          case 1: kx1=0; break;
          case 2: kx2=0; break;
          case 3: kx3=0;
        }
        if(!(P1 & 1<<i/4+4 ))
                        { key=i; if(kn<255) kn++; break; } //有键按下
  }
  
这句 { key=i; if(kn<255) kn++; break; } //有键按下

改成        { key=key_T[i]; if(kn<255) kn++; break; } //有键按下
这是直接查表不需要转换

打赏

参与人数 1家元 +30 收起 理由
shangh + 30 熱心會員

查看全部打赏

回复

使用道具 举报

发表于 2024-4-18 08:59:41 | 显示全部楼层
本帖最后由 kkdkj 于 2024-4-18 09:05 编辑

不知道你用什么语言。有个米思齐图形代编程很好玩,不会单片机的也很容易上手,这里有视频介绍矩阵键盘调位置的,你可以参考一下,悟一下原理。如果你的这个芯片能直接在米思齐上编程就更好了,比着视频学学就行了。
----------------
【mixly图形化单片机编程 61 矩阵键盘,可以用于密码输入、密码校对】
https://www.bilibili.com/video/B ... acd991c004e84fe7554

打赏

参与人数 1家元 +30 收起 理由
shangh + 30 謝謝分享

查看全部打赏

回复

使用道具 举报

发表于 2024-4-18 14:01:35 来自手机浏览器 | 显示全部楼层
所有按键都引出两根线。然后重新排序,想怎么改就怎么改。不用改程序了。哈哈。
回复

使用道具 举报

 楼主| 发表于 2024-4-18 15:06:18 | 显示全部楼层
1065307738 发表于 2024-4-18 14:01
所有按键都引出两根线。然后重新排序,想怎么改就怎么改。不用改程序了。哈哈。 ...

看来也只能这样
回复

使用道具 举报

发表于 2024-4-18 15:09:46 | 显示全部楼层
1065307738 发表于 2024-4-18 14:01
所有按键都引出两根线。然后重新排序,想怎么改就怎么改。不用改程序了。哈哈。 ...

这个思路非常新奇
回复

使用道具 举报

发表于 2024-4-18 16:43:49 | 显示全部楼层
1065307738 发表于 2024-4-18 14:01
所有按键都引出两根线。然后重新排序,想怎么改就怎么改。不用改程序了。哈哈。 ...

发现一个大聪明
回复

使用道具 举报

发表于 2024-4-19 01:32:04 | 显示全部楼层
digitking 发表于 2024-4-17 09:51
改这段,加上一些键位转换也可以

增加一层,高明的思路。
回复

使用道具 举报

发表于 2024-4-19 08:49:10 | 显示全部楼层
1065307738 发表于 2024-4-18 14:01
所有按键都引出两根线。然后重新排序,想怎么改就怎么改。不用改程序了。哈哈。 ...

=重新给键盘PCB排布一下
回复

使用道具 举报

发表于 2024-4-19 10:47:54 | 显示全部楼层
本帖最后由 digitking 于 2024-4-19 10:52 编辑

我给你改好了,你再试试吧。注释里写了修改1和修改2

  1. /*************************************
  2. Q表驱动程序 V3.1
  3. xjw01 于莆田 2010.10
  4. **************************************/
  5. //====================================
  6. #define uchar unsigned char
  7. #define uint  unsigned int
  8. #define ulong  unsigned long
  9. #include <reg52.h>

  10. void delay(uint loop) { uint i; for(i=0;i<loop;i++); } //延时函数
  11. void delay2(uint k){ for(;k>0;k--) delay(10000); } //长延时,k=100大约对应1秒

  12. //========================AD转换=============================
  13. sfr P1ASF = 0x9D; //将P1置为模拟口寄存器(使能),各位中为1的有效
  14. sfr ADC_CONTR = 0xBC; //A/D转换控制寄存器
  15. sfr ADC_res   = 0xBD; //A/D转换结果寄存器
  16. sfr ADC_resl  = 0xBE; //A/D转换结果寄存器

  17. void set_channel(char channel){
  18. P1ASF = 1<<channel;
  19. ADC_CONTR = channel+128; //最高位是电源开关,低3位通道选择
  20. delay(1); //首次打开电源应延迟,使输入稳定
  21. }
  22. uint get_AD2(){
  23. ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  24. while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
  25. ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  26. return ADC_res*4 + ADC_resl;
  27. }

  28. /*
  29. uchar get_AD(){
  30. ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  31. while( !(ADC_CONTR & 0x10) );  //等待A/D转换结束(ADC_FLAG==0)
  32. ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  33. return ADC_res;
  34. }
  35. */
  36. //============================EEPROW偏程=========================
  37. sfr IAP_data  = 0xC2;
  38. sfr IAP_addrH = 0xC3;
  39. sfr IAP_addrL = 0xC4;
  40. sfr IAP_cmd   = 0xC5;
  41. sfr IAP_trig  = 0xC6;
  42. sfr IAP_contr = 0xC7;
  43. /********************
  44. 写字节时,可以将原有数据中的1改为0,无法将0改为1,只能使用擦除命令将0改为1
  45. 应注意,擦除命令会将整个扇区擦除
  46. *********************/
  47. uchar readEEP(uint k){ //读取
  48. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  49. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  50. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  51. IAP_cmd = 1;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  52. IAP_trig = 0x5A;  //先送5A
  53. IAP_trig = 0xA5;  //先送5A再送A5立即触发
  54. return IAP_data;
  55. }
  56. void writeEEP(uint k, uchar da){ //写入
  57. IAP_data = da;    //传入数据
  58. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  59. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  60. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  61. IAP_cmd = 2;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  62. IAP_trig = 0x5A;  //先送5A
  63. IAP_trig = 0xA5;  //先送5A再送A5立即触发
  64. }
  65. void eraseEEP(uint k){ //擦除
  66. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  67. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  68. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  69. IAP_cmd = 3;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  70. IAP_trig = 0x5A;  //先送5A
  71. IAP_trig = 0xA5;  //先送5A再送A5立即触发
  72. }

  73. #define Nda 23
  74. xdata struct Ida{
  75. int bas;    //比值基数
  76. int z[Nda]; //激励电压表
  77. int C,C2;   //主调电容的电大值与最小值,单位0.1pF
  78. int jz[14]; //125等分非线性改正表,jz[0]存放初始温度下的零点电压(初次非线性桥正时的零点电压)而不存0值
  79. } cs;

  80. void cs_RW(char rw){
  81. uchar i,*p = &cs;
  82. if(rw){
  83.   eraseEEP(0);
  84.   for(i=0;i<sizeof(cs);i++) writeEEP(i,p);
  85. }else{
  86.   for(i=0;i<sizeof(cs);i++) p=readEEP(i);
  87. }
  88. }



  89. //=============================DDS部分========================
  90. #define fMax 12500000
  91. xdata ulong feq=600000;
  92. xdata uchar fstep=100;

  93. sbit FSYNC=P2^1; //DDS使能
  94. sbit SCLK=P2^2;  //DDS串行时钟
  95. sbit SDATA=P2^3; //DDS串行数据

  96. void DDS_W16(uint d){ //写32比特数据到DDS
  97.   uchar i;
  98.   SCLK = SDATA = FSYNC=1;  delay(3000);
  99.   FSYNC=0; //使能(或同步)打开,数据开始传送
  100.   delay(5);
  101.   for(i=0;i<16;i++){
  102.     SDATA = d>>15; delay(1);
  103.         SCLK = 0;           delay(1);
  104.         SCLK = 1;           delay(1);
  105.         d<<=1;
  106.   }
  107.   
  108.   FSYNC=1; delay(1);
  109.   SCLK=0;  delay(1);
  110. }

  111. void DDS_init(void){
  112.   DDS_W16(0x2100); //B28=1(28位连续写频置位),选择频率0相位0,RESET=1
  113.   //DDS_W16(0x2500); //B28=1(28位连续写频置位),选择频率0相位1,RESET=1
  114.   //DDS_W16(0x2900); //B28=1(28位连续写频置位),选择频率1相位0,RESET=1
  115.   //DDS_W16(0x2D00); //B28=1(28位连续写频置位),选择频率1相位1,RESET=1
  116.   //当RESET置位后,开始初始化频率和相位
  117.   DDS_W16(0x4000);        //写频率0寄存器的低字节LSB
  118.   DDS_W16(0x4000);        //写频率0寄存器的高字节MSB
  119.   DDS_W16(0x8000);        //写频率1寄存器的低字节LSB
  120.   DDS_W16(0x8000);        //写频率1寄存器的高字节MSB
  121.   DDS_W16(0xC000);        //写相位0
  122.   DDS_W16(0xF000);        //写相位1
  123.   DDS_W16(0x2000);        //28位连续,选择频率0,相位0,RESET=0        
  124. }

  125. void DDS_f(){ //设置频率
  126.   ulong m;
  127.   uint mL,mH;
  128.   if( feq > fMax ) feq = fMax;
  129.   m = feq*10 + feq*11/16 + feq*12/256 + feq*12/256/16 + feq*6/65536; // f* 268435456/ 25000000
  130.   mL = m, mH = m>>14;          //分离出低字节和高字节(各14bit有效)
  131.   mL = (mL & 0x3FFF) + 0x4000; //补上前导01
  132.   mH = (mH & 0x3FFF) + 0x4000; //补上前导01
  133.   DDS_W16(0x2000);        DDS_W16(mL);  DDS_W16(mH); //连续28bit写频,RESET=0时所设频率被应用
  134. }


  135. /**********
  136. 字形编码图
  137.    32
  138.    -
  139. 64| | 128
  140.    -  16
  141. 1| | 8
  142.    _. 4
  143.    2
  144. **********/
  145. uchar code zk[20]={235,136,179,186,216,122,123,168,251,250}; //字库

  146. uchar disp[6]={168,251,250}; char cx=-1; //显示缓存,cx光标位置
  147. sfr P1M1=0x91; //P1端口设置寄存器
  148. sfr P1M0=0x92; //P1端口设置寄存器
  149. sfr P0M1=0x93; //P0端口设置寄存器
  150. sfr P0M0=0x94; //P0端口设置寄存器
  151. sfr P2M1=0x95; //P2端口设置寄存器
  152. sfr P2M0=0x96; //P2端口设置寄存器
  153. sfr P3M1=0xB1; //P3端口设置寄存器
  154. sfr P3M0=0xB2; //P3端口设置寄存器

  155. sbit ds3=P2^4; //数码管扫描口
  156. sbit ds2=P2^5; //数码管扫描口
  157. sbit ds1=P2^6; //数码管扫描口
  158. sbit ds0=P2^7; //数码管扫描口
  159. sbit kx0=P3^4; //键盘扫描口
  160. sbit kx1=P3^5; //键盘扫描口
  161. sbit kx2=P3^6; //键盘扫描口
  162. sbit kx3=P3^7; //键盘扫描口

  163. sbit K0=P3^3;  //调零开关端口(输出)
  164. sbit KP=P3^2;  //电源管理
  165. sbit spk=P2^0; //蜂鸣器



  166. //功能程序开始

  167. xdata uchar menu=1,menuF=0,menu2=0;

  168. void cls(){ char i; for(i=0;i<6;i++) disp=0; } //清屏
  169. void showDig(long f){ //显示数字
  170. uchar i;
  171. cls();
  172. for(i=0;i<6;i++) { disp=zk[f%10], f/=10; if(!f) break; }
  173. }


  174. uchar tms=0,ts=0,tm=0,th=0; ////tms为5ms计数器
  175. uchar tmX=0; //无操作时间(自动关机使用)

  176. void timerInter1(void) interrupt 3 {//T1中断
  177.   TH1=0xa8; TL1+=0x11;
  178.   tms++;
  179.   if(tms==100){
  180.     tms = 0, ts++; //秒跳变
  181.     if(ts==60){
  182.       ts=0, tm++,tmX++;  //分钟跳变
  183.       if(tm==60) tm=0, th++;
  184.       if(th==24) th=0;
  185.           if(tmX==8) KP = 0; //自动关机
  186.         }
  187.   }
  188. }


  189. void timerInter(void) interrupt 1 {//T0中断
  190. }


  191. xdata int V0=0,V1=0,V10=0; //V0调零电压,V1检波电压
  192. int code lineV[14]={0,1,2,3,4,5,10,15,20,25,50,75,100,125}; //娇正输出表(线性表)
  193. int jiaozheng(long v){ //输入已调零的电压值
  194. char i,b;
  195. int a;
  196. if(v<=0) return 0;
  197. for(i=1;i<14;i++) if(v<cs.jz) break;
  198. if(i==14) i=13;
  199. //温漂改正
  200. b = (V0-cs.jz[0])*7/10; //零点漂移量的70%
  201. if(v<170) v += v*b/170;
  202. else     v += b;
  203. //矫正
  204. if(i) a = cs.jz[i-1]; else a = 0;
  205. return lineV[i-1]*10 + (lineV-lineV[i-1])*10*(v-cs.jz[i-1])/(cs.jz-cs.jz[i-1]);
  206. }


  207. uint Qlc(int f, ulong v){ //Q值计算,f单位千赫,非线性v矫正后的电压
  208.   xdata int a = cs.z[Nda-1];
  209.   xdata char i;
  210.   i = f/500, f%=500;
  211.   if(i<Nda-1)  a = cs.z + f*(cs.z[i+1]-cs.z)/500;
  212.   return (v*cs.bas + a/2)/a;
  213. }

  214. void showQ(){ //显示Q
  215.   if(V1>=1023) { disp[0]=disp[1]=disp[2]=disp[3]=128; return; }
  216.   showDig( Qlc(feq/1000,jiaozheng(V1-V0)) );
  217.   disp[1] += 4;
  218. }

  219. void showF(){ //显示频率
  220.   if(ts%4==0){
  221.     showDig(feq%10000);
  222.     disp[3] = 115;
  223.         if(!disp[1]) disp[1]=zk[0];
  224.         if(!disp[2]) disp[2]=zk[0];
  225.   }else{
  226.     showDig(feq/1000);
  227.         if(feq>=10000000) disp[3]+=4;
  228.   }
  229. }
  230. void zeroOff(){ //读取调零值
  231.   spk=1; //关闭蜂鸣器,防音频干扰
  232.   K0=1;  delay2(50); //调零开关置位
  233.   V0=get_AD2();      //读取调零电压
  234.   K0=0;  delay2(50); //调零开关复位
  235. }

  236. xdata ulong fm=0; //中心谐振点
  237. int Q3db=0,C0=0; //3dB Q值,C0分布电容
  238. long Lx = 10000,Cz=5000; //Lx被电感的电感量(单位0.01uH),Cz主调电容值(单位0.1pF)
  239. int readV(ulong f){ feq=f; DDS_f(); delay(60000); return jiaozheng(get_AD2()-V0); } //置频率并读取谐振电压,返回矫正后的电压
  240. void autoF(int maxQ,char N){ //自动查找谐振点,N扫频点数(实扫频2N+1点),通常N=50足够,N<maxQ/2
  241. char i,k; //循环变量
  242. xdata long bc=feq/maxQ;  //扫描步长,建议maxQ=5000设计
  243. char im=0,an=0; int vm=0,qm; //极点变量
  244. xdata int va,vb,v3db;   //偏频计算的变量
  245. xdata long pf,pf1,pf2;  //偏频计算的变量

  246. spk=1; //关闭蜂鸣器,防音频干扰
  247. delay2(100);//等待1秒

  248. //开始扫频,查找极点
  249. fm = feq;
  250. for(k=0;k<2;k++){ //分两次查找,第一次粗调,第二次细调
  251.    an=0, vm=0; //an溢出计数器
  252.    for(i=-N;i<=N;i++){
  253.      feq=fm+i*bc; DDS_f();      //设置频率
  254.      delay(4000); V1=get_AD2(); //读电压
  255.      if(vm<V1) im=i,vm=V1;      //记录最大值
  256.          if(V1>=1023) an++;
  257.    }
  258.    im += an/2, fm+=im*bc; //极值位置
  259.    N=10, bc/=N;
  260. }

  261. vm=jiaozheng(vm-V0), v3db = vm*17/24, qm=Qlc(fm/1000,vm);
  262. //已找到谐振点,下面进一频做3dB分析
  263. pf = fm*5/qm; //带通半宽度
  264. va = readV(fm+pf/2); if(va<v3db) qm*=5,pf/=5; //量程判断
  265. pf1 = pf, pf2 = -pf;
  266. va = readV(fm+pf);      //右频偏1
  267. vb = readV(fm+pf*9/10); //右频偏2
  268. if(vb!=va) pf1 -= (pf/10)*(v3db-va)/(vb-va); //精确右偏频点
  269. va = readV(fm-pf);      //左频偏1
  270. vb = readV(fm-pf*9/10); //左频偏2
  271. if(vb!=va)  pf2 += (pf/10)*(v3db-va)/(vb-va); //精确左偏频点

  272. //谐振点及3dB
  273. fm = fm+(pf2+pf1)/2; //谐振频率
  274. if(pf1>pf2) Q3db = fm*10/(pf1-pf2); else Q3db=0; //计算3dB Q值
  275. if(!Lx) Lx = 2.53303e19/fm/fm/cs.C; //电感量计算,单位0.01uH
  276. Cz = 2.53303e19/fm/fm/Lx;        //谐振总电容,单位0.1pF
  277. if(Q3db>qm) C0 = Cz*(Q3db-qm)/Q3db; else C0=0; //1l是1的长整型
  278. feq = fm; DDS_f();
  279. }

  280. //修改1:按键转码
  281. uchar key_T[16]={
  282. 1,2,3,10,
  283. 4,5,6,11,
  284. 7,8,9,12,
  285. 13,0,14,15
  286. };
  287. //修改1:按键转码结束

  288. main(){
  289. uchar i=0,j=0,kn=0,key=0,act=1;
  290. uchar dispN=0; //显示扫描索引
  291. uchar spkN=0;  //蜂鸣器发声时长

  292. //定时器T0设置,用于信号发生器
  293. TCON=0, TMOD=0x12; //将T0置为自动重装定时器,T1置为定时器
  294. TH1=0xA8, TL1=0x11;
  295. TR1=1;  //T1开始计数
  296. TR0=0;  //T0暂停计数
  297. ET1=1;  //T1开中断
  298. ET0=1;  //T1开中断
  299. EA=1;   //开总中断
  300. PT0=1;  //设置优先级


  301. set_channel(0); //设置AD转换通道
  302. P2M0 = 0xF0;    //P2.4567置为推勉输出
  303. P1M1 = 0x03;    //P1.01置为高阻抗
  304. P3M0 = 0x0C;    //P3.23置为推勉输出口

  305. delay2(50); //等待电路的电压平稳
  306. zeroOff();  //调零
  307. DDS_init(); DDS_f(); //DDS初始化
  308. cs_RW(0); //读取比值基数(调零时已做开机延时,确保电压上升到可读取EEPROW)

  309. while(1){
  310.   V10-=(V10+5)/10; V10+=get_AD2(); V1=(V10+5)/10;  //取检波电压(数字滤波)
  311.   //显示disp
  312.   dispN=(++dispN)%4; //扫描器移动
  313.   ds0=ds1=ds2=ds3=0;
  314.   if(dispN==0) ds0=1;
  315.   if(dispN==1) ds1=1;
  316.   if(dispN==2) ds2=1;
  317.   if(dispN==3) ds3=1;
  318.   if(dispN==cx && tms>100) P0=255; //光标闪烁
  319.   else P0=~disp[dispN]; //显示
  320.   //扫描键盘
  321.   for(i=0,key=255;i<16;i++){
  322.         kx0=kx1=kx2=kx3=1;
  323.         switch(i%4){ //X线置0
  324.           case 0: kx0=0; break;
  325.           case 1: kx1=0; break;
  326.           case 2: kx2=0; break;
  327.           case 3: kx3=0;
  328.         }
  329.         //修改2:键盘转码
  330.         if(!(P1 & 1<<i/4+4 )) { key=key_T[i]; if(kn<255) kn++; break; } //有键按下
  331.   }
  332.   if(i==16) kn=0; //无键按下
  333.   //键盘响应
  334.   if(kn==20) spkN=50,tmX=0; else key=255;   //当按下一定时间后,key才有效,否则无效。spkN发声时长设置
  335.   if(spkN) spkN--, spk=0; else spk=1; //键盘发声
  336.   //菜单系统
  337.   if(key==15) menu=0,menu2=0;
  338.   if(key==12) { if(menuF) menu=menuF, menuF=0; else menuF=menu, menu=255; key=255; } //频率显示键
  339.   if(menuF){ //编辑频率
  340.     if(key<10 ) feq = feq*10+key; //设置频率,有数字键按下则进入编辑状态
  341.         if(key==10) feq = 0;          //清除
  342.         if(key==11) feq *= 1000;      //整千赫输入
  343.         if(key<15) DDS_f();
  344.     showF(); //显示
  345.   }

  346.   if(menu==0){ //显示菜单
  347.     int Vbat;
  348.     set_channel(1); //设置AD转换通道
  349.         delay(20); Vbat = get_AD2(); //读取电池电压
  350.     set_channel(0); //设置AD转换通道
  351.         Vbat = Vbat*14/29;
  352.     showDig(Vbat);
  353.         disp[2]+=4;
  354.         disp[3]=2;
  355.         if(key<15) { menu=key;  continue; }
  356.   }
  357.   if(menu==1){ //显示Q
  358.     if(key<=4) menu2 = key;
  359.     if(key==13) { feq += fstep;  DDS_f(); }    //频率微调
  360.     if(key==14) { feq -= fstep;  DDS_f(); }    //频率微调
  361.         if(key==5)  { feq = 1000000; DDS_f(); }    //设置频率为中波段频率的中心
  362.         if(key==6)  { feq = 3000000; DDS_f(); }    //设置频率为3MHz频率
  363.         if(key==7)  { autoF(200,100); } //宽范围自动粗调谐
  364.            if(key==8)  { fstep=20;  }
  365.            if(key==9)  { fstep=100; }
  366.         if(key==11) { autoF(5000,50); } //窄范围自动细调谐
  367.     if(key==10) { zeroOff(); }   //调零
  368.     if(menu2==0) { if(tms%10==0) showQ();      } //显示Q
  369.         if(menu2==1) { showDig(Q3db); disp[1]+=4;  } //显示3dB法Q值
  370.         if(menu2==2) { showDig(Cz);   disp[1]+=4;  } //显示主调电容
  371.         if(menu2==3) { showDig(C0);   disp[1]+=4;  } //显示分布电容
  372.         if(menu2==4) { //显示电感量
  373.           if(Lx<9999)       { showDig(Lx);    disp[2]+=4; }
  374.           else if(Lx<99999) { showDig(Lx/10); disp[1]+=4; }
  375.           else              { showDig(Lx/100); }
  376.         }
  377.   }
  378.   if(menu==14){ Lx=0; autoF(5000,50); menu=1; key=255; } //电感量测量
  379.   if(menu==2){ //显压显示
  380.    if(key>=0&&key<10) menu2=key;
  381.    if(key==10) zeroOff(); //强制调零
  382.    if(menu2==0) { if(tms%10==0) showDig(jiaozheng(V1-V0)); } //显示矫正后的电压
  383.    if(menu2==1) { if(tms%10==0) showDig(V0); } //显示调零电压
  384.    if(menu2==2) { if(tms%10==0) showDig(V1); } //显示检波电压
  385.   }
  386.   if(menu==3){ //编辑比值基数
  387.     if(key==14) menu2=0;
  388.     if(key==13) menu2=1;
  389.         if(menu2==0){ //设置变压器的比值(例如比值为56,应输入560)
  390.       if(key<10) cs.bas = cs.bas*10+key; //修改
  391.       if(key==10) cs.bas = 0; //清零
  392.           if(key==11) cs_RW(1); //保存
  393.           showDig(cs.bas);
  394.          }
  395.         if(menu2==1){ //设置主调电容的最大容量
  396.       if(key<10) cs.C = cs.C*10+key; //修改
  397.       if(key==10) cs.C = 0; //清零
  398.           if(key==11) cs_RW(1); //保存
  399.           showDig(cs.C);
  400.          }
  401.   }
  402.   if(menu==4){ //编辑激励电压
  403.     //频点选择
  404.     if(key==14&&menu2>0) menu2--;
  405.     if(key==13&&menu2<Nda-1) menu2++;
  406.     //手动修改
  407.     if(key<10) cs.z[menu2] = cs.z[menu2]*10+key; //手动修改
  408.     if(key==10) cs.z[menu2] = 0; //清零
  409.         if(key==0 && cs.z[menu2]==0){ //已清零再输入0则全部清0
  410.           for(i=0;i<Nda;i++) cs.z=0;
  411.         }
  412.         if(key==11){ //保存
  413.       spk=1; //关闭蜂鸣器,防音频干扰
  414.           for(i=0;i<Nda;i++){ //自动检查,如果数据为空则自动测量
  415.             if(cs.z>0&&cs.z<255) continue;
  416.         if(i==0) feq = 300; else feq = i*500;
  417.             feq*=1000; DDS_f();
  418.         delay2(5); V1=get_AD2(); //读电压
  419.             cs.z = jiaozheng(V1-V0);
  420.           }
  421.       cs_RW(1);
  422.         }
  423.         showDig(cs.z[menu2]*10+(menu2/2)%10);
  424.         disp[1]+=4;        if(menu2%2) disp[0]+=4;
  425.   }
  426.   if(menu==5){ //非线性校正数据编辑
  427.     //插值点选择
  428.     if(key==14&&menu2>0) menu2--;
  429.     if(key==13&&menu2<13) menu2++;
  430.     if(key<10) cs.jz[menu2] = cs.jz[menu2]*10+key; //编辑
  431.     if(key==10) cs.jz[menu2] = 0; //清零
  432.         if(key==11) cs_RW(1); //保存
  433.         if(ts%2) { showDig(lineV[menu2]); disp[3]=207; }//显示等分定标电压值
  434.         else showDig(cs.jz[menu2]);        //显示未桥正的电压值(已调零)
  435.   }
  436.   delay(4000);
  437. }//while end
  438. }
复制代码


打赏

参与人数 2家元 +90 收起 理由
shangh + 30 熱心會員,无论对错非常感谢
蓝天白云888 + 60 乐于助人

查看全部打赏

回复

使用道具 举报

 楼主| 发表于 2024-4-20 10:03:37 | 显示全部楼层
本帖最后由 shangh 于 2024-4-20 10:13 编辑
digitking 发表于 2024-4-19 10:47
我给你改好了,你再试试吧。注释里写了修改1和修改2

修改后的代码,键盘需要其他排序只要改你改的这个代码排序就可以是吗?


捕获.JPG

我找到了一种印字与这个Q表键盘非常接近的4x4的硅胶按键,就是“F”键丝印不同,已经买了最后确定就用这个键盘,

就是下图中这种排序,要是改排序没有我说的那样简单,那就自己画一个键盘板子,
目前已经画好了一半,就等买的硅胶按键到货把尺寸量出来键盘就可以完工


IMG_4815.JPG


回复

使用道具 举报

 楼主| 发表于 2024-4-20 14:43:01 | 显示全部楼层
本帖最后由 shangh 于 2024-4-24 13:07 编辑
digitking 发表于 2024-4-19 10:47
我给你改好了,你再试试吧。注释里写了修改1和修改2

用KeivuV4编译你修改后的代码有两句报错,原始源代码不会报错




jg.JPG

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-30 11:03 , Processed in 0.436800 second(s), 13 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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