一些实用的单片机c程序 //16进制<->10进制互换程序 unsigned char d[10]; //用于显示的10位显示缓存 //======================================================== //16进制to10进制输出子程序:显示数据,起始位,结束位,有无小数点 //======================================================== void output(unsigned long dd,unsigned char s,unsigned char e,unsigned char dip) { unsigned long div; unsigned char tm[8],i,j; div=10000000; for (i=0;i<8;i++) { tm[i]=dd/div; dd%=div; div/=10; } for (i=0;i<6;i++) { if (tm[i]!=0) break; tm[i]=nul; } tm[5]|=dip; //小数点控制,请看“串行LED数码管显示驱动程序” j=7; for (i=s;i<e;i++) { d[i]=tm[j]; j--; } } //把显示位5-9位的10进制数转换成为16进制数 unsigned int input(void) { unsigned int dd,dat; dd=10000;dat=0; for (i=5;i<10;i++) { dat+=dd*temp; dd/=10; } return(dat); } /* 89C51系列CPU编程器接收CPU程序*/ #i nclude <reg51.h> #i nclude <intrins.h> #i nclude <absacc.h> #define e 8 #define p 9 #define l 10 sbit led=P3^2; sbit p27=P2^7; sbit p26=P2^6; sbit p36=P3^6; sbit p37=P3^7; sbit rst=P3^3; sbit ale=P3^5; sbit vpp=P3^4; bit b_break; unsigned int adds; // 13.8mS void int_t0(void) interrupt 1 { TH0=-100; b_break=1; } void wait(unsigned char w) { unsigned int t=w*184; b_break=0; TL0=-t%256-1;TH0=-t/256; while (b_break==0) {} } void nop(void) { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } unsigned char command(void) { TH0=-100;b_break=0; while (RI==0) {if (b_break==1) return(0);} RI=0; return(SBUF); } void earsure(unsigned char cpu) { switch (cpu) { case 1: //89C51 case 2:rst=p26=1;p27=p36=p37=0;nop();vpp=1;nop(); ale=0;wait(110);ale=1;nop(); break; case 3: case 4:break; case 5: case 6:break; } } void program(unsigned char cpu) { unsigned int bdata adds=0; unsigned char d; switch (cpu) { case 1: //89C51 case 2: p36=p37=1;rst=1; while (1) { TH0=-100;b_break=0; while (RI==0) {if (b_break==1) return;} RI=0; d=SBUF; //address P0=adds%256; P2=adds/256; p27=1; //data P1=d; nop(); //48clcl //vpp vpp=1; nop(); //48clcl //ale ale=0; wait(1);//100uS ale=1; nop(); //10uS vpp=0; nop(); //48clcl p27=0; nop(); //48clcl P1=0xff; TH0=-100;b_break=0; while (d!=P1) {if (b_break==1) return;} //data polling SBUF=d; adds++; } break; case 3: case 4: case 5: case 6:break; } } void lock(unsigned char cpu) { unsigned char i; switch (cpu) { case 1: //89c51 case 2: //lock 1 rst=p26=p36=p27=p37=1;nop(); vpp=1; nop(); ale=0; // for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop(); //lock 2 rst=p26=p27=1;p36=p37=0;nop(); vpp=1; nop(); ale=0; // for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop(); //lock 3 rst=p26=p36=1;p27=p37=0;nop(); vpp=1; nop(); ale=0; // for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop(); break; case 3: case 4: case 5: case 6:break; } } void main(void) { unsigned char disp,flash,temp,cpu; EA=1; SCON=0xd8;PCON=0x80; TMOD=0x21; TL1=TH1=0xff;TR1=1; TH0=-100;ET0=TR0=1; flash=0x80; while (1) { temp=command(); switch (temp) { case 0: case 1: //89c51 case 2: //89C52 case 3: //80f51 case 4: //80F52 case 5: //87F51 case 6:cpu=temp;SBUF=temp;break;//87f52 case e:SBUF=temp;earsure(cpu);break; //erasure case p:SBUF=temp;program(cpu);break; //program case l:lock(cpu);SBUF=temp;break; //lock default:SBUF=temp;break; } b_break=0; if ((++disp)>flash) {disp=0;led=!led;} } } //HT1380实时时钟驱动程序 sbit clock_dat=P0^1; sbit clock_clk=P0^2; sbit clock_rst=P0^3; sbit a0=ACC^0; sbit a1=ACC^1; sbit a2=ACC^2; sbit a3=ACC^3; sbit a4=ACC^4; sbit a5=ACC^5; sbit a6=ACC^6; sbit a7=ACC^7; void clock_out(unsigned char dd) { ACC=dd; clock_dat=a0;clock_clk=1;clock_clk=0; clock_dat=a1;clock_clk=1;clock_clk=0; clock_dat=a2;clock_clk=1;clock_clk=0; clock_dat=a3;clock_clk=1;clock_clk=0; clock_dat=a4;clock_clk=1;clock_clk=0; clock_dat=a5;clock_clk=1;clock_clk=0; clock_dat=a6;clock_clk=1;clock_clk=0; clock_dat=a7;clock_clk=1;clock_clk=0; } unsigned char clock_in(void) { clock_dat=1; a0=clock_dat; clock_clk=1;clock_clk=0;a1=clock_dat; clock_clk=1;clock_clk=0;a2=clock_dat; clock_clk=1;clock_clk=0;a3=clock_dat; clock_clk=1;clock_clk=0;a4=clock_dat; clock_clk=1;clock_clk=0;a5=clock_dat; clock_clk=1;clock_clk=0;a6=clock_dat; clock_clk=1;clock_clk=0;a7=clock_dat; return(ACC); } unsigned char read_clock(unsigned char ord) { unsigned char dd=0; clock_clk=0; clock_rst=0; clock_rst=1; clock_out(ord); dd=clock_in(); clock_rst=0; clock_clk=1; return(dd); } void write_clock(unsigned char ord,unsigned char dd) { clock_clk=0; clock_rst=0; clock_rst=1; clock_out(ord); clock_out(dd); clock_rst=0; clock_clk=1; } /*单个汉字库字摸提取程序,tc2.0编译*/ #i nclude "stdio.h" #i nclude "dos.h" #i nclude "process.h" #i nclude "string.h" void main(void) { long int num_bytes,qm,wm; unsigned char d,i,j,k,a[132],b[132]; unsigned char * data; unsigned char * hz; static unsigned char dd[103]; FILE *fp; if ((fp=fopen("hzk16f","rb"))==NULL) { printf("can't open hzk16\n"); exit(1); } clrscr(); while (1) { data=(unsigned char *) malloc(33); printf("please input:\n"); scanf("%s",dd); /*输入一个汉字*/ qm=* dd; /*通过区位码计算其在hzk16f文件中的偏移地址*/ qm=qm-161; if (qm>87) exit(0); wm=* (dd+1); wm=wm-161; if (wm>94) exit(0); num_bytes=((long)qm*94+wm)*32; fseek(fp,num_bytes,SEEK_SET); fgets(data,33,fp); for (i=0;i<32;i++) b[i]=* data++; for (i=0;i<32;i+=2) a[i/2]=b[i]; for (i=0;i<32;i+=2) a[i/2+16]=b[i+1]; for (i=8;i<16;i++) b[i]=a[i]; for (i=8;i<16;i++) a[i]=a[i+8]; for (i=8;i<16;i++) a[i+8]=b[i]; /*转换,hzf16f在电脑的储存格式是以行为字节计算的,一般的lcd都采用以列为字节计算*/ for (k=0;k<32;k+=8) { for (j=0;j<8;j++) { d=0; for (i=0;i<8;i++) { if (a[i+k]>=0x80) { switch (i) { case 0:d+=1;break; case 1:d+=2;break; case 2:d+=4;break; case 3:d+=8;break; case 4:d+=0x10;break; case 5:d+=0x20;break; case 6:d+=0x40;break; case 7:d+=0x80;break; } } } for (i=0;i<8;i++) a[i+k]<<=1; b[j+k]=d; } } clrscr(); printf("/*%s:*/\n",dd); /*输出0x00格式的16进制数*/ for (k=0;k<32;k+=8) { for (j=0;j<8;j++) printf("0x%x,",b[j+k]); printf("\n"); } getch(); } } //按键扫描驱动程序 unsigned char key,key_h,kpush; unsigned int key_l; //按键连接到p1.0、p1.1、p1.2 void int_t0(void) interrupt 1 { unsigned char dd,i; TL0=TL0+30;TH0=0xfb; //800 /* 按键判别 */ if ((P1&0x7)==0x7) { if ((key_l>30)&&(key_l<800)&&(key_h>30)) { //释放按键,如果之前按键时间少于1秒,读入键值 key=kpush; } if ((++key_h)>200) key_h=200; key_l=0; if (key>=0x80) key=0; //如果之前的按键为长按1秒,清除键值 } else { kpush=P1&0x7; key_l++; if ((key_l>800)&&(key_h>30)) { //如果按键超过1秒,键值加0x80标志长按键 key=kpush|0x80; key_h=0; key_l=0; } } } void main(void) { TMOD=0x1;TR0=1;ET0=1;EA=1; while (1) { while (!key) {} switch (key) { case 1:break; case 2:break; } } //串行驱动led显示, //一个74hc595位移寄存器驱动三极管驱动led位, //两个74hc595驱动led段,方式位5位x8段x2=10个数码管 //5分频,每次扫描时间位1.25ms //定义特殊符号 #define nul 0xf #define qc 0xc #define qb 0xb #define q_ 0xa #define q__ 0xd #define q___ 0xe #define qp 0x10 #define qe 0x11 #define qj 0x12 #define qn 0x13 #define qf 0x14 #define qa 0x15 #define qr 0x16 #define qd 0x17 #define qu 0x18 #define ql 0x19 #define qh 0x1a #define qwen 0x1b #define qt 0x1c #define qla 0x1d #define qlb 0x1e #define qlc 0x1f #define qld 0x20 #define qle 0x21 #define qlf 0x22 #define qlg 0x23 #define qldp 0x24 //显示段信息,不同led排列组合的段信息只需更改8个数值即可。 //因此,该定义具有通用性。 // 显示 // -d 20 // |c 40 |e 10 // - g 80 // |b 2 |f 4 // _a1 .dp 8 #define pa 1 #define pb 2 #define pc 0x40 #define pd 0x20 #define pe 0x10 #define pf 4 #define pg 0x80 #define pdp 8 //-------------- #define l0 pdp+pg #define l1 255-pf-pe #define l2 pdp+pc+pf #define l3 pdp+pc+pb #define l4 pdp+pa+pb+pd #define l5 pdp+pb+pe #define l6 pdp+pe #define l7 pdp+pc+pg+pb+pa #define l8 pdp #define l9 pdp+pb #define la pdp+pa #define lb pdp+pd+pe #define lc pdp+pg+pe+pf #define ld pdp+pc+pd #define le pdp+pe+pf #define lf pdp+pe+pf+pa #define l_ 255-pg #define lnul 255 #define ll pdp+pg+pd+pf+pe #define lp pdp+pa+pf #define lt pdp+pd+pe+pf #define lr pdp+pe+pf+pg+pa #define ln pdp+pg+pa #define lh pdp+pd+pe+pa #define ly pdp+pb+pd #define lu pdp+pg+pd #define l__ pdp+pg+pb+pc+pe+pf #define l___ l__-pg #define l_1 255-pa #define l_2 255-pa-pg #define lj 255-(pe+pf+pa) #define lwen 255-(pd+pe+pg+pb) #define lall 0 #define lla 255-pa #define llb 255-pb #define llc 255-pc #define lld 255-pd #define lle 255-pe #define llf 255-pf #define llg 255-pg #define lldp 255-pdp //串行送出的位信息,目前是10位led显示。 unsigned char code un_dig[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb}; //串行送出的短信息。 unsigned char code un_disp[]={l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l_,lb,lc,l__,l___,lnul,lp,le,lj,ln,lf,la,lr,ld,lu, ll,lh,lwen,lt,lla,llb,llc,lld,lle,llf,llg,lldp,lnul}; sbit d_clk=P0^0; //移位时钟 sbit d_dat=P0^1; //移位数据 sbit d_st=P0^2; //移位锁定 unsigned char dig; //位扫描计数器 unsigned char d[10]; //显示缓冲 //送出8位串行数据 void out_disp(unsigned char dd) { unsigned char i; for (i=0;i<8;i++) { if (dd&1) d_dat=1; else d_dat=0; d_clk=0; dd>>=1; d_clk=1; } } //控制小数点和闪烁,显示数据|0x040表示有小数点;显示数据|0x80表示闪烁。 void out_displ(unsigned char dd) { if (dd>=0x80) { if (s001>flash_time) {out_disp(0xff);return;} } dd&=0x7f; if (dd>=0x40) { dd=un_disp[dd&0x3f]^pdp; } else dd=un_disp[dd]; out_disp(dd); } unsigned int s001; //闪烁时间参考 void int_t0(void) interrupt 1 { unsigned char dd; TL0=TL0+30;TH0=0xfb; //800 time++; if ((++s001)>=800) s001=0; // 显示 if ((++dig)>4) dig=0; d_st=0; dd=d[dig+5]; out_displ(dd); dd=d[dig]; out_displ(dd); out_disp(un_dig[dig]); d_st=1; } void main(void) { unsigned char i; TMOD=0x1; TR0=ET0=1; EA=1; for (i=0;i<10;i++) d[i]=i; //display test while (1) {} }

评论