数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 145|回复: 3

[软件] C 语言代码 --- 宏 中【指针内容】更改为【数组下标】

[复制链接]
发表于 前天 11:05 | 显示全部楼层 |阅读模式
花了差不多一天时间,终于看懂原有逻辑,将 原有 宏中的 指针部分,替换为 数组下标,

逻辑功能一目了然。
结果已经验证OK.
和大家共享!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
发表于 前天 11:27 | 显示全部楼层
厉害,可以帮忙分析一下许老师电桥的代码吗?


  1. //zz20130224 程序升级为V5.5版本;lcd_goto2(9)处显示位置修改,并处理末尾消隐;修正相对测量功能不能启动的问题
  2. //zz20130223 完善手动档的相关显示,把频率和档位显示语句放到return之前,否则显示不完善
  3. //zz20130222 修改图形ES(R)为字符型
  4. //程序基于 2004程序_3.0_全自动电桥V5.4

  5. //==========================================================================
  6. //  LCR表驱动程序 V2.0
  7. //  许剑伟 于莆田 2012.01
  8. //==========================================================================
  9. //==========================================================================
  10. #define uchar unsigned char
  11. #define uint  unsigned int
  12. #define ulong  unsigned long
  13. #include <reg52.h>
  14. #include <math.h>

  15. //==========================================================================
  16. // 项目:LCD1602 四线驱动程序
  17. // 设计要点:
  18. //     LCD1602 的运行速度慢,而单片机运行的速度快,因此容易因为速度不
  19. //     匹配造成调试失败。因此,调试之前应准确测试lcd_delay() 延时函数
  20. //     准确的延时量,如果不能满足注释中的要求,则应调整循次数。每步操
  21. //     作所需的延时量,按照数据手册指标指行,同时留下足够的时间余量。
  22. // 硬件连接:
  23. //     至少需要9条线,电源线2条,7条信号线。信号线详见程序中的接口定义。
  24. //     清注意对LCD1602对比度的调节,否则无显示。
  25. // 设计:许剑伟,于莆田,2010.12
  26. //==========================================================================
  27. sbit lcd_RS = P2^5; //数据命令控制位,0命令1数据
  28. sbit lcd_RW = P2^6; //读写位,0写1读
  29. sbit lcd_EN = P2^7; //使能位,下降沿触发
  30. sbit lcd_D4 = P0^3; //数据端口D4
  31. sbit lcd_D5 = P0^2; //数据端口D5
  32. sbit lcd_D6 = P0^1; //数据端口D6
  33. sbit lcd_D7 = P0^0; //数据端口D7
  34. //==========================================================================
  35. code char path[40]={
  36. 0x00,0x00,0x0e,0x11,0x11,0x0a,0x1b,0x00,
  37. 0x00,0x11,0x11,0x13,0x1d,0x10,0x10,0x10,
  38. 0x0e,0x11,0x1f,0x11,0x11,0x0e,0x00,0x00,
  39. 0x1C,0x10,0x1B,0x12,0x1B,0x01,0x07,0x00,
  40. 0x04,0x0e,0x1f,0x04,0x1f,0x0e,0x04,0x00
  41. };//自定义符号

  42. code uchar abc[][5]={
  43. "  err","   40","  120","  360"," 1080","   1K","   3K","   9K","  27K","  10K",
  44. "  30K","  90K"," 270K"," 100K"," 300K"," 900K"," 2.7M","   13","  4.5","  1.5"
  45. };
  46. code char *lcr[7]   = {"2000", " 200", "20.0","2.00", " 20", " 20","2.0"};
  47. code char *feqc[3]  = {"100Hz"," 1KHz" ,"7.8KH"};
  48. code char *zero[2]  = {"Open zero......","Short zero...OK."};

  49. char binLian=0,ATA=0,ATD=0;
  50. char OX[8]={0,0,0,0,0,0,8,0};
  51. int DDS3=1, c3 = 0,c4 = 0;
  52. xdata char isQ=1,REL=0;
  53. xdata uchar menu=1,menu2=0; //菜单变量
  54. xdata float TR,TX; //清零数据
  55. xdata float RELDAT; //相对测量数据
  56. uint ph=0, phM=256, feq=977; //相位,phM相位步进值

  57. void lcd_delay(int n){ //LCD专用延时函数
  58.   //32MHz钟频下,约循环3000次延迟1毫秒
  59.   int i,j;
  60.   if(n<0)    { for(i=0;i< 30;i++); return; } //10us
  61.   if(n== 0)  { for(i=0;i<150;i++); return; } //50us
  62.   for(;n;n--){ for(j=0;j<3000;j++);        } //n毫秒
  63. }
  64. //==========================================================================
  65. void lcd_B(char f, uchar c, char t){ //控制四线式接口LCD的7个脚
  66.   //f=0写命令字, f=1写RAM数据, f=2读地址(或读忙), f=3读RAM数据
  67.   lcd_EN = 0;
  68.   lcd_RS = f%2;
  69.   lcd_RW = f/2%2;
  70.   //移入高四位
  71.   lcd_D4 = c & 16;
  72.   lcd_D5 = c & 32;
  73.   lcd_D6 = c & 64;
  74.   lcd_D7 = c & 128;
  75.   lcd_EN = 1;  lcd_delay(-1);  lcd_EN = 0; //使能脉冲
  76.   if(f==4) { lcd_delay(t); return; }
  77.   //移入低四位
  78.   lcd_D4 = c & 1;
  79.   lcd_D5 = c & 2;
  80.   lcd_D6 = c & 4;
  81.   lcd_D7 = c & 8;
  82.   lcd_EN = 1;  lcd_delay(-1);  lcd_EN = 0; //使能脉冲
  83.   lcd_delay(t);  //不同的命令,响应时间不同,清零命令需要2ms
  84. }
  85. //==========================================================================
  86. void lcd_init(){ //LCD1602 初始化
  87.   //启动四线模式须势行9个步骤,初始化所须耗时较长,约65ms,时限不可减
  88.   lcd_delay(20); //启动lcd之前须延时大于15ms,直到VDD大于4.5V
  89.   lcd_B(4, 0x30, 9); //置8线模式,须延时大于4.1ms
  90.   lcd_B(4, 0x30, 5); //置8线模式,须延时大于100us
  91.   lcd_B(4, 0x30, 5); //置8线模式,手册中未指定延时
  92.   lcd_B(4, 0x20, 5); //进入四线模式
  93.   lcd_B(0, 0x28, 5); //四线模式双行显示
  94.   lcd_B(0, 0x0C, 5); //打开显示器
  95.   lcd_B(0, 0x80, 5); //RAM指针定位
  96.   lcd_B(0, 0x01, 5); //启动清屏命初始化LCD
  97. }
  98. //==========================================================================
  99. //=========================几个功能常用函数=================================
  100. void lcd_cls()         { lcd_B(0, 0x01+0, 2);  } //清屏
  101. void lcd_cur0()        { lcd_B(0, 0x0C+0, 0);  } //隐藏光标
  102. void lcd_goto1(uchar x){ lcd_B(0, 0x80+x, 0); } //设置DDRAM地址,第1行x位
  103. void lcd_goto2(uchar x){ lcd_B(0, 0xC0+x, 0); } //设置DDRAM地址,第2行x位
  104. void lcd_goto3(uchar x){ lcd_B(0, 0x94+x, 0); } //设置DDRAM地址,第3行x位
  105. void lcd_goto4(uchar x){ lcd_B(0, 0xD4+x, 0); } //设置DDRAM地址,第4行x位
  106. void lcd_putc(uchar d) { lcd_B(1, 0x00+d, 0);  } //字符输出
  107. void lcd_puts(uchar *s){ for(; *s; s++) lcd_B(1,*s,0); } //字串输出
  108. //==============字符显示函数====================

  109. void lcd_putp(float a,float b,char bo,char n, float qmin){ //带单位显示复数,n是单位下限,qmin是最小位权值(用于限定有效数字)
  110.   code uchar dwB[] = {'p','n',1,'m',0,'k','M','G'}; //单位表
  111.   char i,j, c=0,digW=4, h=3, fh[2]={' ','+'};
  112.   long d,q,qm,Q=1; //最高位权
  113.   float f,g=1,k=1;
  114.   if(bo==2){k=2;}
  115.   if(a<0) fh[0] = '-', a = -a;
  116.   if(b<0) fh[1] = '-', b = -b;
  117.   if(a>b) f = a; else f = b;
  118.   for(i=1;i<4;i++) Q *= 10;
  119.   for(i=0;i<3;i++){ if(f*g >= k*1000) g/=1000, c++; } //以3位为单位移动小数点,右移
  120.   for(i=0;i<n;i++){ if(f*g < k)     g*=1000, c--; }   //以3位为单位移动小数点,左移
  121.   if ((n==1)&&(c==-1)){
  122.   digW=2;                 //移动1位小数点
  123.   }else if ((n==2)&&(c==-2)){
  124.   if(feq!=7813) {digW=2;   //移动1位小数点
  125.   }else{ digW=3; }         //移动2位小数点
  126.   }else if ((n==4)&&(c==-4)){
  127.   if(feq!=7813) {digW=2;   //移动1位小数点
  128.   }else{ digW=3; }         //移动2位小数点
  129.   }
  130.   for(i=1;i<digW && f*g<k*Q;i++) g*=10,h--;           //继续移动小数点,使之满字
  131.   qm = g*qmin;
  132.   for(i=0;i<2;i++){
  133.    if(i) d = b*g+0.5;      //取出实部
  134.    else  d = a*g+0.5;      //取出虚部
  135.    if(qm) d+=qm/2, d-=d%qm;//去除小于qmin的尾数
  136.    if(d>=Q*20) d=(d+0.5)/10, h++;
  137.    q = Q;
  138.    if(d>=Q*10){
  139.      d -= Q*10;
  140.      if(fh[i]=='-') {lcd_puts("-1");
  141.      }else          {lcd_puts(" 1");}
  142.    }else{
  143.    lcd_putc(fh[i]); if(bo==2)lcd_putc('0');      //显示符号
  144.    }
  145.    for(j=0; j<4; j++){  //数字输出
  146.     lcd_putc(d/q+48);      //数字
  147.     if(j==h) lcd_putc('.');//小数点
  148.     d %= q, q /= 10;  
  149.    }
  150.    if(!bo||bo==2) break;     //不显示虚部
  151.   }
  152.   if((n!=1)&&(dwB[c+4]==0))lcd_putc(' '); else lcd_putc(dwB[c+4]);//单位
  153.   if((n==1)&&(dwB[c+4]==0)) OX[6]=32; else OX[6]=8; //自动单位
  154. }

  155. void lcd_putf(float a, char n, float qmin) //带单位显示浮点数,n是单位下限
  156.   { lcd_putp(a,0,0,n,qmin); }
  157. void lcd_int(int a,char w){ //定宽显示正整数
  158.   char i=0, s[5] = {' ',' ',' ',' ',' '};
  159.   if(a<0) { a=-a; lcd_puts("-"); }
  160.   else    lcd_puts(" ");
  161.   do{
  162.    s[i++] = a%10+48;
  163.    a /= 10;
  164.   }while(a);
  165.   for(;w;w--) lcd_putc(s[w-1]);
  166. }

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

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

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



  188. //==========================================================================
  189. //==================================EEPROW偏程==============================
  190. sfr IAP_data  = 0xC2;
  191. sfr IAP_addrH = 0xC3;
  192. sfr IAP_addrL = 0xC4;
  193. sfr IAP_cmd   = 0xC5;
  194. sfr IAP_trig  = 0xC6;
  195. sfr IAP_contr = 0xC7;
  196. /********************
  197. 写字节时,可以将原有数据中的1改为0,无法将0改为1,只能使用擦除命令将0改为1
  198. 应注意,擦除命令会将整个扇区擦除
  199. *********************/
  200. int eepEn = 0;
  201. void saEEP(){ //触发并EEP保护
  202. if(eepEn==12345) IAP_trig = 0x5A;  //先送5A
  203. if(eepEn==12345) IAP_trig = 0xA5;  //先送5A再送A5立即触发
  204. IAP_cmd = 0;      //关闭令,保护
  205. IAP_contr = 0;    //关EEPROM,保护
  206. IAP_trig = 0;
  207. IAP_addrL = 255; //设置读取地址的低字节,地址改变才需要设置
  208. IAP_addrH = 255; //设置读取地址的高字节,地址改变才需要设置
  209. }
  210. uchar readEEP(uint k){ //读取
  211. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  212. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  213. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  214. IAP_cmd = 1;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  215. saEEP(); //触发并保护
  216. return IAP_data;
  217. }
  218. void writeEEP(uint k, uchar da){ //写入
  219. IAP_data = da;    //传入数据
  220. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  221. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  222. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  223. IAP_cmd = 2;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  224. saEEP(); //触发并保护
  225. }
  226. void eraseEEP(uint k){ //擦除
  227. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  228. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  229. IAP_contr = 0x81; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  230. IAP_cmd = 3;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  231. saEEP(); //触发并保护
  232. }


  233. xdata struct Ida{
  234. char zo[3];//三个频率下的零点改正值
  235. char j1;   //相位补偿(3倍档)
  236. char j2;   //相位补偿(10倍档)
  237. char J[4];  //相位补偿(V/I变换器)
  238. char R[4]; //下臂电阻修正(40,1k,10k,100k)
  239. char g1;   //增益修正(3倍档)
  240. char g2;   //增益修正(10倍档)
  241. char phx; //1kHz以下相位改正
  242. char R4b; //100k档7.8kHz频率下的幅度补偿
  243. char G2b; //9倍档7.8kHz频率下的幅度补偿
  244. char feq; //频率修正
  245. char ak;  //AD斜率修正
  246. float QRs[3],QXs[3]; //短路清零数据
  247. float QRo[3],QXo[3]; //开路清零数据
  248. } cs;

  249. void cs_RW(char rw){
  250. uchar i,*p = &cs;
  251. const int offs=512;
  252. if(rw){
  253.   delay2(20); //等待(防止掉电误识别键盘而调用本函数)
  254.   eraseEEP(offs);
  255.   for(i=0;i<sizeof(cs);i++) writeEEP(i+offs,p[i]);
  256. }else{
  257.   for(i=0;i<sizeof(cs);i++) p[i]=readEEP(i+offs);
  258. }
  259. }

  260. //==========================================================================
  261. //==================================LCR主程序===============================
  262. //==========================================================================
  263. sfr P1M1=0x91; //P1端口设置寄存器
  264. sfr P1M0=0x92; //P1端口设置寄存器
  265. sfr P0M1=0x93; //P0端口设置寄存器
  266. sfr P0M0=0x94; //P0端口设置寄存器
  267. sfr P2M1=0x95; //P2端口设置寄存器
  268. sfr P2M0=0x96; //P2端口设置寄存器
  269. sfr P3M1=0xB1; //P3端口设置寄存器
  270. sfr P3M0=0xB2; //P3端口设置寄存器


  271. sbit spk=P2^3; //蜂鸣器
  272. sbit Kb=P2^4;  //量程开关B
  273. sbit Ka=P2^2;  //量程开关A
  274. sbit DDS2=P1^2;//移相方波输出口
  275. sbit K3=P1^7;
  276. sbit K4=P1^6;
  277. sbit K5=P1^5;  //7.8kHz滤波开关
  278. sbit K6=P1^4;
  279. sbit K8=P2^0;  //100Hz滤波开关
  280. sbit K32=P1^1; //32kHz发生器


  281. //==============低频信号DDS相关参数====================
  282. //PCA相关寄存器
  283. sfr CMOD = 0xD9;   //钟源选择控制等
  284. sfr CH = 0xF9;     //PCA的计数器
  285. sfr CL = 0xE9;     //PCA的计数器
  286. sfr CCON = 0xD8;   //PCA控制寄存器
  287. sfr CCPAM0 = 0xDA; //PCA模块0工作模式寄存器
  288. sfr CCPAM1 = 0xDB; //PCA模块1工作模式寄存器
  289. sfr CCAP0L = 0xEA; //模块0捕获寄存器低位
  290. sfr CCAP0H = 0xFA; //模块0捕获寄存器高位
  291. sfr IPH = 0xB7;

  292. sbit PPCA  = IP^7;   //PCA的中断优先级设置
  293. sbit CCF0  = CCON^0; //PCA的模块0中断标志
  294. sbit CCF1  = CCON^1; //PCA的模块1中断标志
  295. sbit CR = CCON^6;    //PCA计数器使能

  296. uchar *ph8 = (char*)&ph;    //ph的高8位地址
  297. xdata float feqX=976.6; //实际输出频率
  298. uchar code sinB[256]={
  299. //查询表中不可装载零值,否则会造成无中断产生
  300. 255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247,246,245,243,242,240,239,237,236,234,232,230,229,227,225,222,220,
  301. 218,216,214,211,209,206,204,201,199,196,194,191,188,185,183,180,177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131,
  302. 128,125,122,119,116,112,109,106,103,100, 97, 94, 91, 88, 85, 82, 79, 76, 73, 71, 68, 65, 62, 60, 57, 55, 52, 50, 47, 45, 42, 40,
  303.   38, 36, 34, 31, 29, 27, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10,  9,  8,  7,  6,  5,  4,  4,  3,  2,  2,  1,  1,  1,  1,  1,
  304.    1,  1,  1,  1,  1,  1,  2,  2,  3,  4,  4,  5,  6,  7,  8,  9, 10, 11, 13, 14, 16, 17, 19, 20, 22, 24, 26, 27, 29, 31, 34, 36,
  305.   38, 40, 42, 45, 47, 50, 52, 55, 57, 60, 62, 65, 68, 71, 73, 76, 79, 82, 85, 88, 91, 94, 97,100,103,106,109,112,116,119,122,125,
  306. 128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,177,180,183,185,188,191,194,196,199,201,204,206,209,211,214,216,
  307. 218,220,222,225,227,229,230,232,234,236,237,239,240,242,243,245,246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255
  308. };
  309. uchar code fbB[256]={ //方波DDS查询表
  310. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  311. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  312. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  313. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  314. uchar chuX=0; //方波DDS初相
  315. //==============低频信号DDS函数====================
  316. void PWM_init(){ //把PCA置为PWM
  317.   CMOD = 2;   //0000 0010 计数源选择,钟源取fosc/2
  318.   CL = CH = 0;
  319.   CCAP0L = CCAP0H = 192; //占空比为25%
  320.   //CCPAM0=0x42;//0100 0010,PCA的模块0设置为PWM模式,无中断
  321.   CCPAM0=0x53;//0101 0011,PCA的模块0设置为PWM模式,有中断,下降沿中断
  322.   PPCA = 1;   //优先中断
  323.   IPH |= 128;
  324.   //CR = 1;   //开始计数
  325.   EA = 1;     //开总中断
  326. }

  327. void PCAinter(void) interrupt 7 {//PCA中断
  328.   uchar x,y;
  329.   CCF0=0; //清除中断请求,以免反复中断
  330.   x = *ph8;        //截断正弦相位累加器,取高8位
  331.   y = x + chuX;    //方波相位
  332.   CCAP0H = sinB[x];//正弦DDS输出
  333. if(DDS3) {  DDS2 = fbB[y];   //方波DDS输出
  334. }else {DDS2 = 0;}
  335.   ph += phM;       //相位累加
  336.   K32 = ~K32;
  337. }
  338. void setDDS(uint f){ //参考时钟是c=(fosc/2)/256=32000000/2/256=62500,频率f=c*phM/2^16
  339. feq = f;
  340. phM=f*65536.0/62500; //phM=f*2^16/62500
  341. feqX = 62500.0*phM/65536*(1+cs.feq/10000.0); //实际输出频率
  342. ph = 0;              //高频时,使波形对称
  343. if(!f) CR=0; else CR=1;
  344. }

  345. //相位控制函数
  346. xdata char xw=0; //相位
  347. void set90(char k){ //设置方波的相位差
  348.   k %= 4;
  349.   if(k<0) k += 4;
  350.   chuX = k*64;   //移相0~270度
  351.   xw = k;
  352. }
  353. void set902() { set90(xw+1); } //相位步进

  354. //==============量程控制函数====================
  355. xdata char rng=1; //量程
  356. void setRng(char k){//切换量程
  357. if(k>3) k=3;
  358. if(k<0) k=0;
  359. Kb = k & 2, Ka = k & 1;  //40欧--100k欧
  360. rng = k;
  361. }
  362. void setRng2(){ setRng( (rng+1)%4);} //量程步进       

  363. //==============增益控制函数====================
  364. char curGain=1; //当前增益索引号
  365. void setGain(char k){ //设置电路增益
  366.   if(k>3) k=3;
  367.   if(k<0) k=0;
  368.   K4 = k & 2, K6 = k & 1; //1倍--27倍
  369.   curGain = k;
  370. }
  371. void setGain2(){ setGain((curGain+1)%4); }


  372. //==============AD非线性改正与过采样=================
  373. uint getAD10(){ //120次采样,用reentrant申明,有的单片机无法运行
  374. uchar i;
  375. long c;
  376. for(i=0;i<250;i++) c += getAD2();
  377. return (c+12)/25;
  378. }
  379. uint getAD10b(){ //120次采样,用reentrant申明,有的单片机无法运行
  380. xdata uint c = 0, c2 = 0;
  381. uchar i;
  382. for(i=0;i<250;i++){
  383.   ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  384.   while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
  385.   ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  386.   c  += ADC_resl;
  387.   c2 += ADC_res;
  388. }
  389. c3 = c;
  390. c = ( c2*4L + c )/25;
  391. c3= ( c2*4L + c3 ) -c*25;
  392. return c;
  393. }



  394. //==============LCR测量====================
  395. code float ga[4] =  {  1,   3,   9,  27 }; //增益表
  396. code float dwR[4] = { 40, 1e3, 1e4, 1e5 }; //各档电阻表
  397. xdata int Vxy[12]={0,0,0,0,1,1}; //Vxy[Vx1,Vy1,Vx2,Vy2,g1,g2]
  398. xdata char Sxw[4]={0,1,0,1};    //保存正确相位
  399. xdata int Vz[24];               //LCR测量结果队
  400. xdata uchar tim=0,tims=0;
  401. xdata char pau=0; //暂停坐标自动旋转


  402. #define Vfull 9600
  403. #define gad (9600/30)
  404. uchar mT = 6; //测量速度,mT取值为6或12或24时,可以消除数字噪声,尾数不动,但不利于于取平均
  405. //==============设置频率====================
  406. xdata char feqK=1; //频率索引号
  407. void setF(char k){
  408.   if(k==-1) k = (feqK+1)%3; //步进
  409.   feqK = k;
  410.   if(k==0) { setDDS(100);   K5=0; K8=1; mT=12; } //置为100Hz
  411.   if(k==1) { setDDS(977);   K5=0; K8=0; mT=6;  } //置为1kHz
  412.   if(k==2) { setDDS(7813);  K5=1; K8=0; mT=6;  } //置为7.8125kHz
  413.   TH1 = 150, TL1 = 171; //置为20ms
  414.   tims = 0;
  415.   tim = 0;
  416.   ph = 0;
  417. }
  418. int absMax(int a,int b){ //取两个数绝对值最大者
  419.   if(a<0) a = -a;
  420.   if(b<0) b = -b;
  421.   if(b>a) a = b;
  422.   return a;
  423. }

  424. char yc1=0,yc2=0; //溢出标识
  425. char slw = 1; //降速倍率
  426. char chg=0;   //量程切换标记
  427. void timerInter1(void) interrupt 3 {//T1中断,LCR数据采集
  428. code int y[5]={0,-15,30,24,0}; //满度用30
  429. code int x[5]={4900,5090,5140,5500,6120};
  430.   char g,gb,Rb,i; int c=0,cc=0;
  431.   tims++;
  432.   if(tims>=mT/slw) tims = 0, tim++, c = 1;
  433.   if(tim>=4) tim=0;
  434.   if(pau) return;
  435.   if(!c) return; //tim未进位触发
  436.   c = getAD10b();   //读取电压值
  437.   c4= c;
  438.   cc= c3;
  439.   c -= cs.zo[feqK];
  440. if(cs.ak!=0){
  441. for(i=0;i<4;i++){ //非线性改正
  442.   if(c<x[i]||c>=x[i+1]) continue;
  443.   c += cs.ak*( y[i] + (y[i+1]-y[i]) * ((int)(c-x[i])) / (x[i+1]-x[i]) ) / 30;
  444.   break;
  445. }
  446. }
  447.   
  448.   Vxy[tim] = xw<2 ? c : -c;  //保存当前电压
  449.   Vxy[tim+6] = xw<2 ? cc : -cc;  //保存当前电压
  450.   Vxy[tim/2+4] = curGain;    //保存当前增益
  451.   Sxw[tim] = ( Sxw[tim]+(c<0 ? 2 : 0) )%4;  //相位翻转(预测下次的相位采用值)
  452.   if(tim==1||tim==3){ //上下臂切换
  453.     if(tim==1) { K3=1, c = absMax(Vxy[2],Vxy[3]), g=Vxy[5]; yc2 = c>Vfull ? 1:0; }//切换到下臂
  454.     if(tim==3) { K3=0, c = absMax(Vxy[0],Vxy[1]), g=Vxy[4]; yc1 = c>Vfull ? 1:0; }//切换到上臂
  455.     gb=g, Rb=rng;
  456.     if(c>Vfull){ if(g==0&&rng>0&&K3&&isQ) Rb=rng-1; gb=0; }
  457.     else if(c<gad*1 ) gb = g+3; //增加27倍
  458.     else if(c<gad*3 ){ gb = g+2;if(c<gad*2&&rng>=1&&rng<=2&&K3&&isQ ) { gb=0; Rb=rng+1; }} //增加9倍
  459.     else if(c<gad*9)  gb = g+1; //增加3倍
  460.         if(gb>3) gb = 3;
  461.     if(g==3&&rng<3&&K3&&isQ) { gb=0; Rb=rng+1; }
  462.     if(g==0&&c<gad*1&&rng<3&&K3&&isQ) { gb=0; Rb=rng+1; }

  463.         setRng(Rb); setGain(gb); //置量程
  464.     if(gb!=g || Rb!=rng) slw = 2, chg++; //量程正在改变,则加速测量
  465.     if(tim==3){ if(!chg) slw=1; chg=0; }
  466.   }
  467.   set90( Sxw[ (tim+1)%4 ] ); //相位旋转
  468.   if(tim==3){ for(i=0;i<12;i++) Vz[i+12]=Vz[i], Vz[i]=Vxy[i]; }
  469. }


  470. void showR(char binLian, char showk){ //显示LCR
  471.   xdata float a=0,b=0,c=0,qq=0,dd=0,e,w,L,C;
  472.   xdata int gr=cs.R[rng], g1=cs.g1, g2=cs.g2;
  473.   xdata int g12 = g1 + g2;          //增益最大补偿
  474.   xdata int j12 = (int)cs.j1+cs.j2; //相位最大补偿
  475.   xdata float RELOUT;
  476.   xdata long RELTMP;
  477.   xdata float JD = 0, G = 0, cJD;   //补偿变量
  478.   xdata float v[4];
  479.   xdata char ATC=0,ATE=0,d2=0,d3=1;
  480.   xdata float LCR[3];
  481.   //LCR计算
  482.   if(feqK<0||feqK>2) return;
  483.   if(feq==7813&&rng==3) gr += cs.R4b; //7.8kHz时下臂修正量
  484.   //可控增益单元的增益修正、相位补偿量
  485.   if(feq==7813) g2 += cs.G2b;  //7.8kHz时9倍档修正量
  486.   if(Vz[4] == 1) JD += cs.j1,  G += g1;
  487.   if(Vz[4] == 2) JD += cs.j2,  G += g2;
  488.   if(Vz[4] == 3) JD += j12,    G += g12;
  489.   if(Vz[5] == 1) JD -= cs.j1,  G -= g1;
  490.   if(Vz[5] == 2) JD -= cs.j2,  G -= g2;
  491.   if(Vz[5] == 3) JD -= j12,    G -= g12;
  492.   JD = (JD - cs.J[rng]) * feqX/7813/2000;
  493.   if(feq==977) JD -= cs.phx/2000.0;
  494.   cJD = 1 - JD*JD/2;
  495.   v[0] = Vz[0]+Vz[12]+(Vz[6]+Vz[18])/25.0;
  496.   v[1] = Vz[1]+Vz[13]+(Vz[7]+Vz[19])/25.0;
  497.   v[2] = Vz[2]+Vz[14]+(Vz[8]+Vz[20])/25.0;
  498.   v[3] = Vz[3]+Vz[15]+(Vz[9]+Vz[21])/25.0;
  499.   a = (+( 1.0*v[2]*v[2] + 1.0*v[3]*v[3] )*((ga[Vz[4]] / ga[Vz[5]]) /(dwR[rng]*(1+gr/10000.0))))+(+( 1.0*v[2]*v[2] + 1.0*v[3]*v[3] )*((ga[Vz[4]] / ga[Vz[5]]) /(dwR[rng]*(1+gr/10000.0))))*G/10000;  //增益补偿
  500.   b = (-( 1.0*v[0]*v[2] + 1.0*v[1]*v[3] ))*cJD - (-( 1.0*v[2]*v[1] - 1.0*v[0]*v[3] ))*JD; //相位补偿
  501.   c = (-( 1.0*v[0]*v[2] + 1.0*v[1]*v[3] ))*JD + (-( 1.0*v[2]*v[1] - 1.0*v[0]*v[3] ))*cJD; //相位补偿  
  502. if(showk){
  503.   w = 2*3.1415926*feqX;
  504.   if((showk==5)||(showk==8)||(showk==10)||(showk==13)||(showk==15)||(showk==18)||(showk==19)){d3=0;}
  505.   if((showk==1)||(showk==2)||(showk==3))  //校准项
  506.   {
  507.   showk=0;
  508.   lcd_puts("Z=");
  509.   lcd_putf(c4-cs.zo[feqK],0,0);
  510.   return;
  511.   }
  512.   if(binLian){ //并联
  513.     e = (b*b+c*c)/a;
  514.   if(d3){
  515.     lcd_puts("R=");
  516.         lcd_putp(e/b, 0,2,1, 1e-4); //显示并联复阻抗,显示到毫欧
  517.   }else{
  518.   if((showk==10)||(showk==13)||(showk==15)||(showk==18)){
  519.         C = -c/e/w;
  520.         L = +e/c/w;
  521.     if(C>-2e-12) { lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F'); } //显示并联C值,显示到pF
  522.     else         { lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H'); } //显示并联L值,显示到uH
  523.   }else{
  524.     lcd_putc(10);lcd_puts("=");
  525.     lcd_putf(atan2(c,b)*180/3.1415926,0,0); //显示角度
  526.     lcd_puts("    ");
  527. }
  528. }
  529.   }else{ //串联
  530.     e = a;
  531.   if(d3){
  532.     lcd_puts("R=");
  533.         lcd_putp(b/e, c/e, 2, 1, 1e-5); lcd_putc(OX[6]); //定义欧姆符号_显示串联复阻抗,显示到毫欧
  534.   }else{
  535.   if((showk==10)||(showk==13)||(showk==15)||(showk==18)){
  536.         C = -e/c/w;
  537.         L = +c/e/w;
  538.     if(L<-2e-8) { lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F'); } //显示C值,显示到pF
  539.     else        { lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H'); } //显示L值,显示到uH
  540.   }else{
  541.     lcd_putc(10);lcd_puts("="); /////////////////////////////lcd_putc(10)相位角自定义符号
  542.     lcd_putf(atan2(c,b)*180/3.1415926,0,0); //显示角度
  543.     lcd_puts("    ");
  544.   }
  545.   }
  546. }
  547. return;
  548. }

  549.   if(binLian==20){ //测量开路残余值
  550.   if(rng==0){
  551.   TR += b/a, TX += c/a; //短路残余阻抗
  552.   }
  553.   if(rng==3){
  554.   a = (b*b+c*c)/a;
  555.   TR += b/a, TX += c/a; //开路残余导抗
  556.   }

  557.   return;
  558.   }

  559.   if(binLian==21){ //是否应用清零
  560.     isQ = (isQ+1)%2;
  561.     return;
  562.   }

  563.   w = 2*3.1415926*feqX;
  564.   if(isQ){ //自动手动,此处为自动  ////////////////////////////////////////////////////////////////
  565.   if(rng==0){
  566.     b -= cs.QRs[feqK]*a, c -= cs.QXs[feqK]*a;//短路清零
  567.   }
  568.   if(rng>1){
  569.     a = (b*b+c*c)/a;       
  570.     b -= cs.QRo[feqK]*a, c -= cs.QXo[feqK]*a; //开路清零
  571.     a = (b*b+c*c)/a;
  572. }

  573.   if(ATA!=0){
  574.   if(ATD==0) { if(rng>1)ATE=1;else ATE=0;  } //置为100Hz
  575.   if(ATD==1) { ATE=1;  } //置为1kHz
  576.   if(ATD==2) { ATE=0;  } //置为7.8125kHz
  577.   }else      { if(rng>1)ATE=1;else ATE=0; }

  578.   if(feq==100)  LCR[0]=2e3,LCR[1]=2e-1,LCR[2]=2e7,d2=1;
  579.   if(feq==977)  LCR[0]=2e2,LCR[1]=2e-2,LCR[2]=2e7,d2=2;
  580.   if(feq==7813) LCR[0]=2e1,LCR[1]=2e-3,LCR[2]=2e6,d2=3;

  581.   if(ATE){ //并联
  582.     e = (b*b+c*c)/a;
  583.         C = -c/e/w;
  584.         L = +e/c/w;
  585.     if(C>-2e-12) { ATC=1; }
  586.     else         { ATC=2; }
  587.     if(fabs(e/b)<fabs(e/c)) { ATC=3; }
  588.   }else{ //串联
  589.     e = a;
  590.         C = -e/c/w;
  591.         L = +c/e/w;
  592.     if(L<-2e-8)  { ATC=1; }
  593.     else         { ATC=2; }
  594.     if(fabs(b/e)>fabs(c/e)) { ATC=3; }
  595.    }


  596.   qq = fabs(c/b); //计算Q
  597.   if(!b||qq>999) qq = 999;
  598.   dd = fabs(b/c); //计算D
  599.   if(!c||dd>=10) dd = 9.999;

  600.   if(ATA!=0){ATC=ATA;}

  601.   lcd_goto1(0);
  602.   if(ATC==0){

  603.   }else if(ATC==1){
  604.   if(ATE){ //并联
  605.   lcd_puts("Cp");
  606.     if(C>-2e-12) {
  607.     if(fabs(C)<LCR[1]) {lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F');  //显示并联C值,显示到pF
  608.     }else{lcd_puts(" C>");lcd_puts(lcr[d2]);lcd_puts("mF");}
  609.     }
  610.     else         { lcd_puts(" ---OL---"); }
  611.   }else{ //串联
  612.   lcd_puts("Cs");
  613.     if(L<-2e-8)  {
  614.     if(fabs(C)<LCR[1]) {lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F');  //显示串联C值,显示到pF
  615.     }else{lcd_puts(" C>");lcd_puts(lcr[d2]);lcd_puts("mF");}
  616.     }
  617.     else         { lcd_puts(" ---OL---"); }
  618.   }

  619.   }else if(ATC==2){
  620.   if(ATE){ //并联
  621.   lcd_puts("Lp");
  622.     if(C>-2e-12) { lcd_puts(" ---OL---"); }
  623.     else         {
  624.     if(fabs(L)<LCR[0]) { lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H');   //显示并联L值,显示到uH
  625.     }else{lcd_puts(" L>");lcd_puts(lcr[d2-1]);lcd_puts(" H");}
  626.     }
  627.   }else{ //串联
  628.   lcd_puts("Ls");
  629.     if(L<-2e-8) { lcd_puts(" ---OL---"); }
  630.     else         {
  631.     if(fabs(L)<LCR[0]) { lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H');   //显示串联L值,显示到uH
  632.     }else{lcd_puts(" L>");lcd_puts(lcr[d2-1]);lcd_puts(" H");}
  633.     }
  634.   }


  635.   }else if(ATC==3){
  636.   if(ATE){ //并联
  637.   lcd_puts("Rp");
  638.    if(fabs(e/b)<LCR[2]) {  lcd_putp(e/b, 0,2,1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  639.    else                 { lcd_puts(" R>");lcd_puts(lcr[d2+3]);lcd_puts(" M");lcd_putc(OX[6]); }
  640.   }else{ //串联
  641.   lcd_puts("Rs");
  642.    if(fabs(b/e)<LCR[2]) { lcd_putp(b/e, 0,2,1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  643.    else                 { lcd_puts(" R>");lcd_puts(lcr[d2+3]);lcd_puts(" M");lcd_putc(OX[6]); }
  644.   }
  645. }

  646.   lcd_goto2(0);
  647.   lcd_puts("Q=");
  648.   lcd_putf(qq,0,0); //显示Q
  649.   lcd_goto3(0);
  650.   lcd_puts("D=");
  651.   lcd_putf(dd,0,0); //显示D

  652.   lcd_goto4(0);
  653.   if(REL) {
  654.   lcd_putc(4);lcd_puts("=");
  655.   if(ATC==0){
  656.   }else if(ATC==1){if(RELDAT==0){RELDAT=C;RELOUT=0;}else{RELOUT=(C-RELDAT)/RELDAT*100.0;}
  657.   }else if(ATC==2){if(RELDAT==0){RELDAT=L;RELOUT=0;}else{RELOUT=(L-RELDAT)/RELDAT*100.0;}
  658.   }else if(ATC==3){
  659.   if(ATE){ //并联
  660.   if(RELDAT==0){RELDAT=e/b;RELOUT=0;}else{RELOUT=((e/b)-RELDAT)/RELDAT*100.0;}
  661.   }else{ //串联
  662.   if(RELDAT==0){RELDAT=b/e;RELOUT=0;}else{RELOUT=((b/e)-RELDAT)/RELDAT*100.0;}
  663.   }
  664.   }
  665.    if(RELOUT<-99.9)RELOUT=-100;
  666.    if(RELOUT>99.9)RELOUT=100;

  667.   if (fabs(RELOUT)==100){
  668.   if (RELOUT>99.9) lcd_puts("   OL  %"); else lcd_puts("-  OL  %");
  669.   }else{
  670.    RELTMP=RELOUT*1000+0.5;
  671.    lcd_putf(RELTMP/1000.0,0,0); lcd_puts("%");
  672.   }
  673.   if(!ATA){ATA=ATC;}
  674.   }else{
  675.   RELDAT=0;

  676.   lcd_putc(10);lcd_putc('=');
  677.   lcd_putf(atan2(c,b)*180/3.1415926,0,0);lcd_puts(" "); //显示角度
  678.   }


  679.   lcd_goto2(9);          ///////////////////////////////////////////////
  680.   if(ATC==3){
  681.   if(ATE){ //并联
  682.   lcd_puts(" Xp");
  683.    if(fabs(e/c)<LCR[2]) { lcd_putf(e/c, 1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  684.    else                 { lcd_puts(" X>");lcd_puts(lcr[d2+3]);lcd_puts("M");lcd_putc(OX[6]);}//lcd_puts(" "); }
  685.   }else{ //串联
  686.   lcd_puts(" Xs");
  687.    if(fabs(c/e)<LCR[2]) { lcd_putp(c/e, b/e, 0, 1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  688.    else                 { lcd_puts(" X>");lcd_puts(lcr[d2+3]);lcd_puts("M");lcd_putc(OX[6]);}//lcd_puts(" "); }

  689.   }
  690.   }else{
  691.   if(ATE){ //并联
  692.   lcd_puts(" RP");
  693.    if(fabs(e/b)<LCR[2]) {lcd_putf(e/b, 1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  694.    else                 { lcd_puts(" R>");lcd_puts(lcr[d2+3]);lcd_puts("M");lcd_putc(OX[6]);}//lcd_puts(" "); }
  695.   }else{ //串联
  696.   lcd_puts("ESR");//lcd_putc(11); //lcd_putc(11)是自定义的es(R)图形
  697.   //lcd_putc('R');
  698.   if(fabs(b/e)<LCR[2]) { lcd_putp(b/e, c/e, 0, 1, 1e-4); lcd_putc(OX[6]);} //显示电阻
  699.   else                 { lcd_puts(" R>");lcd_puts(lcr[d2+3]);lcd_puts("M");lcd_putc(OX[6]);}//lcd_puts(" "); }
  700.   }
  701.   }

  702.   lcd_goto1(11);
  703.   if(ATA==0||ATD==0){
  704.   if(ATA==0) lcd_puts("  AUTO   ");
  705.   if(ATA==1) lcd_puts("  AUTO-C ");
  706.   if(ATA==2) lcd_puts("  AUTO-L ");
  707.   if(ATA==3) lcd_puts("  AUTO-R ");
  708.   }else{
  709.   if(ATE) lcd_puts("   P "); else lcd_puts("   S ");
  710.   if(feq==100)  lcd_putc('A');
  711.   if(feq==977)  lcd_putc('B');
  712.   if(feq==7813) lcd_putc('C');
  713.   lcd_putc(rng+49); //显示量程
  714. }
  715.   lcd_goto3(9);
  716.   lcd_puts("   ");
  717.   if(Vz[4]!=0&&rng==0) {for(OX[5]=0;OX[5]<5;OX[5]++){ lcd_putc(abc[16+Vz[4]][OX[5]]); }lcd_putc(8);}
  718.   else {for(OX[5]=0;OX[5]<5;OX[5]++){ lcd_putc(abc[rng*4+Vz[5]+1][OX[5]]); }lcd_putc(8);}
  719.   lcd_goto4(10);
  720.   if(feq==100)  lcd_puts("   100Hz  ");
  721.   if(feq==977)  lcd_puts("    1KHz  ");
  722.   if(feq==7813) lcd_puts("  7.8KHz  ");

  723.   //lcd_goto2(19);lcd_puts(" ");
  724.   
  725.   }else{        //以下为手动
  726.   //显示量程信息
  727.   lcd_goto4(0); //第四行显示
  728.   if(isQ) lcd_puts("Auto/");  else lcd_puts("Hand/"); //显示自动手动
  729.   if(binLian) lcd_puts("p");  else lcd_puts("s"); //显示串联并联
  730.   lcd_puts(" ");
  731.   lcd_goto4(7);//第四行显示频率
  732.   if(feq==100)  lcd_puts(" 100Hz ");
  733.   if(feq==977)  lcd_puts("  1KHz ");
  734.   if(feq==7813) lcd_puts("7.8KHz ");
  735.   lcd_goto4(14); ////////////////////////////////////zz
  736.   if(rng==0)  {lcd_puts("40");lcd_putc(244);lcd_puts("  ");} //////zz
  737.   if(rng==1)  {lcd_puts("1K");lcd_putc(244);lcd_puts("  ");} //////zz
  738.   if(rng==2)  {lcd_puts("10K");lcd_putc(244);lcd_puts(" ");} //////zz
  739.   if(rng==3)  {lcd_puts("100K");lcd_putc(244);} ///////////////////zz

  740. if(!isQ){  //手动
  741.   if(yc1&&rng!=3){ lcd_goto1(2); lcd_puts(" Overflow,high  ");lcd_goto2(2); lcd_puts("              ");} //未知高阻溢出
  742.   if(yc2&&rng!=0){ lcd_goto1(2); lcd_puts(" Overflow,low    ");lcd_goto2(2); lcd_puts("              ");} //未知低阻溢出
  743.   if(yc1||yc2){ lcd_goto2(2); lcd_puts("                  ");lcd_goto3(2); lcd_puts("                  "); return; }
  744. }


  745.   //电学量显示  if(!a) { lcd_cls(); lcd_puts("DIV 0"); return; }

  746.   if(binLian){ //并联
  747.     e = (b*b+c*c)/a;
  748.     lcd_goto1(0); lcd_puts("R=");
  749.         lcd_putf(e/b, 1, 1e-4); //显示并联复阻抗,显示到毫欧
  750.     lcd_putc(OX[6]);
  751.         lcd_putf(e/c, 1, 1e-4); //显示并联复阻抗,显示到毫欧
  752.         lcd_putc(OX[6]);lcd_puts("  ");
  753.         C = -c/e/w;
  754.         L = +e/c/w;
  755.     lcd_goto2(0);
  756.      if(C>-2e-12) {lcd_puts("C="); lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F'); } //显示并联C值,显示到pF
  757.     else          {lcd_puts("L="); lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H'); } //显示并联L值,显示到uH
  758.    lcd_puts("         ");
  759.   }else{ //串联
  760.     e = a;
  761.     lcd_goto1(0); lcd_puts("R=");         //////////////////////////////////////////////////////////////////////
  762.         lcd_putp(b/e, c/e, 1, 1, 1e-4); lcd_putc(OX[6]); //定义欧姆符号_显示串联复阻抗,显示到毫欧
  763.     lcd_puts("    ");
  764.         C = -e/c/w;
  765.         L = +c/e/w;
  766.     lcd_goto2(0);
  767.     if(L<-2e-8) {lcd_puts("C="); lcd_putp(C, 0,2,4, 1e-14); lcd_putc('F'); } //显示C值,显示到pF
  768.     else        {lcd_puts("L="); lcd_putp(L, 0,2,2, 5e-9 ); lcd_putc('H'); } //显示L值,显示到uH
  769.    lcd_puts("         ");
  770.   }

  771.   qq = fabs(c/b); //计算Q
  772.   if(!b||qq>999) qq = 999;
  773.   dd = fabs(b/c); //计算D
  774.   if(!c||dd>=10) dd = 9.999;

  775.   lcd_goto3(0); //跳转第三行
  776.   lcd_puts("Q="); //显示标识
  777.   lcd_putf(qq,0,0); //显示Q//lcd_putf(c,0,0); //显示Q

  778.   lcd_puts(" ");
  779.   lcd_putc(10);lcd_putc('=');
  780.   lcd_putf(atan2(c,b)*180/3.1415926,0,0); //显示角度

  781.   lcd_puts(" ");

  782.   lcd_goto1(17);
  783.   if((feq==7813)&&(rng==0)&&(!binLian)&&(!isQ)&&(L<-2e-8)){lcd_puts("ESR");}//else{lcd_puts("   ");}//lcd_goto1(19);lcd_puts(" ");}        ///zz

  784. //  lcd_goto4(14);
  785. //  if(Vz[4]!=0&&rng==0) {for(OX[5]=0;OX[5]<5;OX[5]++){ lcd_putc(abc[16+Vz[4]][OX[5]]); }lcd_putc(8);}
  786. //  else {for(OX[5]=0;OX[5]<5;OX[5]++){ lcd_putc(abc[rng*4+Vz[5]+1][OX[5]]); }lcd_putc(8);}

  787. }
  788. }
  789. //void timerInter(void) interrupt 1 {}//T0中断

  790. main(){
  791. uchar i=0,s=0,key=0;
  792. uchar dispN=0; //显示扫描索引
  793. uchar spkN=0;  //蜂鸣器发声时长
  794. uint nn=0;
  795. int kn=0;
  796. char mo=0; //编辑显示开关
  797. lcd_init(); //初始化LCD
  798. lcd_cur0(); //隐藏光标
  799. lcd_B(0, 0x40, 0); //定义欧姆符号_设置CGRAM地址,写指令
  800. for(i=0;i<40;i++)lcd_B(1, 0x00+path[i], 0); //定义欧姆符号_把数据送入CGRAM地址内
  801. lcd_goto1(0);//定义欧姆符号_光标定位
  802. lcd_puts("LCR 3.0");
  803. lcd_goto2(0);
  804. lcd_puts("XJW Putian,2012");
  805. delay2(500); //启动延时
  806. eepEn= 12345;
  807. cs_RW(0);   //读EEPROM

  808. TCON=0, TMOD=0x12; //将T0置为自动重装定时器,T1置为定时器
  809. TH1 = 0, TL1 = 0;
  810. TR1=1;  //T1开始计数
  811. TR0=0;  //T0暂停计数
  812. ET1=1;  //T1开中断
  813. ET0=1;  //T1开中断
  814. EA=1;   //开总中断
  815. //PT0=1;  //设置优先级

  816. set_channel(0); //设置AD转换通道
  817. P2M0 = 0xFF;    //P2.01234567置为推勉输出
  818. P1M0 = 0xFE;    //P1.1234567置为推换口
  819. P1M1 = 0x01;    //P1.0置为高阻抗
  820. P2 = 0x0F;


  821. PWM_init(); //DDS初始化
  822. set90(2);   //初始设置相位
  823. setRng(1);  //初始设置量程
  824. setGain(1); //初始设置增益
  825. setF(1);    //DDS初始设置为1kHz
  826. while(1){
  827.   //显示disp

  828.   //1键-X,2键-R,3键-L,4键-C,5键-Q,6键-F,7键-Rng,8键-Menu

  829.   nn++;
  830.   //扫描键盘
  831.   key = ~P3;
  832.   if(key&&kn<255) kn++; else kn=0;
  833.   for(i=0;key;i++) key/=2; key=i;
  834.   if(menu==7&&key<3){
  835.   if(kn==4) spkN=10,kn=-14; else key=0;      //校准数值加速
  836.   }else{
  837.   if(kn==4) spkN=10; else key=0;   //当按下一定时间后key才有效。spkN发声时长设置
  838.   }

  839.   //菜单系统
  840.   if(key==8){//菜单键
  841.     lcd_cls();    lcd_puts(" LCR Set Options");
  842.     lcd_goto2(0); lcd_puts(" Exit:X  Ver:5.5");
  843.     menu=0; key=0; mo=0; pau=0;
  844.     for(i=0;i<3;i++)OX[i]=3.1415;

  845.     delay(10000);
  846.   }
  847.   if(menu>=1 && menu<=3){
  848.     if(key==7) setRng2(); //量程步进
  849.     if(key==6) setF(-1);  //设置频率
  850.     delay(10000);
  851.   }
  852.   if(menu==0){ //显示量程和菜单
  853.     if(key) lcd_cls();
  854.         if(key>=1 && key<=7) {menu = key, menu2 = 0;if (key==1)isQ=1;}
  855.         key = 0;
  856.     DDS3 = 1;
  857.     delay(10000);
  858.   }  //1键-X,2键-R,3键-L,4键-C,5键-Q,6键-F,7键-Rng,8键-Menu
  859.   if(menu==1){ //LCR测量
  860.     if(key==1) if(isQ){ ATA++;ATD=0;REL=0;if(ATA>3){ATA=0;}}else{binLian = (binLian+1)%2;} //L/C/R 模式
  861.     if(key==2) if(isQ){ ATD++;REL=0;if(ATD>2){ATD=0;}} //串并联测量模式选择
  862.     if(key==3) {showR(21,0);REL=0;} //自动手动切换
  863.     if(key==4) {
  864.   if((rng==3)||(rng==0)){
  865.   lcd_cls();if(rng==3){lcd_puts(zero[0]);}else{lcd_puts(zero[1]);}delay2(100);
  866.   for(i=0;i<3;i++){
  867.   lcd_goto2(2);
  868.   if(feq==100)  delay2(150);
  869.   lcd_puts(feqc[feqK]);lcd_goto2(9);lcd_puts(" ");
  870.   delay2(100);
  871.   TR = 0, TX = 0;
  872.   for(s=0;s<4;s++){lcd_goto2(9);lcd_putc(51-s);if(feq==100){delay2(150);}else{delay2(75);}showR(20,0);}
  873.   if(rng==3){
  874.   cs.QRo[feqK] = TR/4.0, cs.QXo[feqK] = TX/4.0; //开路残余导抗
  875.   }
  876.   if(rng==0){
  877.   cs.QRs[feqK] = TR/4.0, cs.QXs[feqK] = TX/4.0; //短路残余阻抗
  878.   }
  879.   setF(-1);
  880.   }
  881.   cs_RW(1);
  882.   lcd_goto1(0);if(rng==3){lcd_puts(zero[0]);}else{lcd_puts(zero[1]);}delay2(100);
  883.   }
  884.   REL=0;
  885.   } //清零
  886.     OX[7]++;
  887.     if(OX[7]>15){OX[7]=0;showR(binLian,0);}
  888.     delay(12000);
  889.   }
  890.     if(key==5) {REL = (REL+1)%2;spkN=0;}

  891.   if(menu==2){
  892.     lcd_goto1(0);
  893.     lcd_puts("up:");  lcd_putc(Vxy[4]+48);
  894.     lcd_puts(" dw:"); lcd_putc(Vxy[5]+48);
  895.    delay(10000);
  896.   }
  897.   if(menu==3){ //手动调试
  898.     pau = 1;
  899.     if(key==1) setGain2();//增益控制
  900.     if(key==2) { };
  901.     if(key==3) K3=~K3;    //切换上下臂
  902.     if(key==4) set902();  //相位旋转
  903.     lcd_goto1(0);
  904.     lcd_puts(" xw="); lcd_putc(xw+48);      //相位索引号
  905.     lcd_puts(" K3="); lcd_putc(K3?49:48);   //K3状态
  906.     lcd_puts(" Ga="); lcd_putc(curGain+48); //增益索引号
  907.     lcd_goto2(0);
  908.     if(nn%32==0) lcd_int(getAD10(),5);
  909.     delay(10000);
  910.   }
  911.   if(menu>=4 && menu<=5){
  912.     delay(10000);
  913.   }
  914.   if(menu==6){ //频率修正
  915.     if(key==1) cs.feq += 1; //X键增
  916.     if(key==2) cs.feq -= 1; //R键减
  917.     if(key==3) { cs_RW(1); setF(feqK); } //L键保存
  918.     if(OX[0]!=cs.feq){ lcd_cls();OX[0]=cs.feq;
  919.     lcd_goto1(0); lcd_puts("Feq correct");
  920.     lcd_goto2(0); lcd_putf(cs.feq,0,0);}
  921.         delay(10000);
  922.   }
  923.   if(menu==7){ //校准
  924.         code char *csR[19]   = {
  925.      "Z0 :000", "Z1 :000", "Z2 :000",
  926.      "R1 : 40", "R1X: 40",
  927.      "ak : 25",
  928.      "R2 : 1k", "R2X: 1k",
  929.      "R3 :10k", "R3X:10k",
  930.      "R4 :.1M", "R4b:.1M", "R4X:.1M",
  931.      "G1 : 3k", "G1X: 3k",
  932.      "G2 : 9k", "G2b: 9k", "G2X: 9k",     
  933.      "phX: 1k"
  934.      };
  935.     char *p,bc=1, feqD=1,rngD=1;
  936.         static char kc=0;
  937.         isQ = 0;
  938.     lcd_goto2(5);
  939.      if(menu2==0)  p = cs.zo+0,      feqD=0, rngD=0; //100Hz零点校准,接入20k欧电阻  //Z0 77
  940.     if(menu2==1)  p = cs.zo+1,      feqD=1, rngD=0; //1kHz零点校准,接入20k欧电阻  //Z1 74
  941.     if(menu2==2)  p = cs.zo+2,      feqD=2, rngD=0; //7.8kHz零点校准,接入20k欧电阻        //Z2 44
  942.     if(menu2==3)  p = cs.R+0, bc=2, feqD=1, rngD=0; //VI变换器模值校准,接入40欧         //R1 20
  943.     if(menu2==4)  p = cs.J+0,       feqD=2, rngD=0; //40R相位  //R1X 0
  944.     if(menu2==5)  p = &cs.ak,       feqD=1, rngD=0; //AD校准 //ak 0
  945.     if(menu2==6)  p = cs.R+1, bc=2, feqD=1, rngD=1; //VI变换器模值校准,接入1k欧         //R2 0
  946.     if(menu2==7)  p = cs.J+1,       feqD=2, rngD=1; //1k相位  //R2X        -2
  947.     if(menu2==8)  p = cs.R+2, bc=2, feqD=1, rngD=2; //VI变换器模值校准,接入10k欧  //R3 2
  948.     if(menu2==9)  p = cs.J+2,       feqD=2, rngD=2; //10k相位  //R3X -6(2)
  949.     if(menu2==10) p = cs.R+3, bc=2, feqD=1, rngD=3; //VI变换器模值校准,接入100k欧  //R4        24
  950.     if(menu2==11) p = &cs.R4b,bc=2, feqD=2, rngD=3; //7.8kHz频率100k档幅度校准        //R4b 28
  951.     if(menu2==12) p = cs.J+3,       feqD=2, rngD=3; //100k相位        //R4X 29
  952.     if(menu2==13) p = &cs.g1, bc=2, feqD=1, rngD=1; //运放3倍增益校准,接入3.3k欧电阻  //G1 -2
  953.     if(menu2==14) p = &cs.j1,       feqD=2, rngD=1; //3倍档相位         G1X 32
  954.     if(menu2==15) p = &cs.g2, bc=2, feqD=1, rngD=1; //运放9倍增益校准,接入10k欧电阻         //G2 -10
  955.     if(menu2==16) p = &cs.G2b,bc=2, feqD=2, rngD=1; //7.8kHz频率9倍档幅度校准  //G2b 2
  956.     if(menu2==17) p = &cs.j2,       feqD=2, rngD=1; //9倍档相位         //G2X 24(34)
  957.     if(menu2==18) p = &cs.phx,      feqD=1, rngD=1; //1kHz以下相位校准,接入1k欧电阻         //phx 0
  958.     if(menu2<3) DDS3=0; else DDS3=1;
  959.     if(key==1) *p += bc ; //X键增
  960.     if(key==2) *p -= bc ; //R键减
  961.     if(key==3) { cs_RW(1); setF(feqK); } //L键保存
  962.     if(key==4) *p = 0;   //C键清除
  963.         if(key==5) { if(menu2==0) menu2=18; else menu2--; mo=0; }
  964.         if(key==6) { if(menu2==18)menu2=0;  else menu2++; mo=0; }
  965.         if(key==7) mo = (mo+1)%2;
  966.         if(key==4){ //恢复到默认值
  967.           if(++kc==5){
  968.            kc = 0;
  969.        cs.j1 = 32, cs.j2 = 24;
  970.        cs.g1 = -2,  cs.g2 = -10;
  971.        cs.zo[0] = 76;
  972.        cs.zo[1] = 78;
  973.        cs.zo[2] = 78;
  974.        cs.J[0] = 0,cs.J[1] = -2, cs.J[2] = -6, cs.J[3] = 29;
  975.        cs.R[0] = 20,cs.R[1] = 0,cs.R[2] = 2,cs.R[3] = 24;
  976.        cs.R4b = 28, cs.G2b = 2,cs.phx = cs.feq = 0;
  977.            cs.ak = 0;
  978.            for(i=0;i<3;i++) cs.QRs[i] = cs.QXs[i] = cs.QRo[i] = cs.QXo[i] = 0;
  979.           }
  980.         }
  981.         else { if(key) kc=0; }
  982.         //显示
  983.         if(mo){
  984.      OX[1]=3.1415;OX[2]=3.1415;
  985.          if(feqD!=feqK) setF(feqD);
  986.          if(rngD!=rng)  setRng(rngD);
  987.      if(menu2>=3&&menu2<=7) showR(0,0);
  988.      else showR(1,0);
  989.         }else{
  990.          if(feqD!=feqK) setF(feqD);
  991.          if(rngD!=rng)  setRng(rngD);
  992.      if(menu2>=3&&menu2<=7) showR(0,menu2+1);
  993.      else showR(1,menu2+1);
  994.     if(OX[1]!=*p||OX[2]!=menu2){ OX[1]=*p;OX[2]=menu2;
  995.           lcd_cls();
  996.       lcd_goto1(0); lcd_puts(csR[menu2]);lcd_puts(" X:+ R:-"); //输出参数名称
  997.       lcd_goto2(0); lcd_int(*p,3);     //输出参数值
  998.       }
  999.      delay(10000);
  1000.     }
  1001.   }
  1002. if (menu!=7){
  1003.   if(spkN) spkN--, spk=0; else spk=1; //键盘发声
  1004. }

  1005. }//while end
  1006. }
  1007. //==========================================================================

复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 前天 11:37 | 显示全部楼层
猪小呆 发表于 2025-6-11 11:27
厉害,可以帮忙分析一下许老师电桥的代码吗?

不懂这个。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-6-13 21:49 , Processed in 0.218400 second(s), 9 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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