#include <pic.h><br />//此程序实现"数控步进直流稳压电源"的功能,调试时为了避免资源冲突,应使实验板上的拔码开关S8拔向高电平<br />//本程序设定S9键为增加键,当按住S9键不松开时,输出Vout以0.1V连续步进,<br />//直至键S9松开,当以一定的时间间隔点动S9键时,输出Vout也为点动步进<br />//递减键S11的功能与S9基本相同时,输出电压的值显示在3个LED上<br />unsigned char R1,R2,R3,TXDATA,LEDF,BJF,COUNTW,data;<br />unsigned int i;<br />const char table[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0xFF};<br />//不带小数点的显示段码表<br />const char table0[11]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10,0xFF};<br />//带小数点的的显示段码表<br />unsigned char s[4]; //定义一个显示缓冲数组<br />//把需要显示的数字装入显示缓冲数组<br />void sfz()<br />{ <br /> s[0]=R3;<br /> s[1]=R2;<br /> s[2]=R1;<br /> s[3]=0x0A; //最后一个LED显示"DARK"<br />}<br />//系统各寄存器初始化子程序<br />void initial()<br />{<br /> R1=0X00;<br /> R2=0X00;<br /> R3=0X00;<br /> sfz(); //把需要显示的数字装入显示缓冲数组<br /> TXDATA=0X00;<br /> LEDF=0X01;<br /> BJF=0X01;<br /> TRISB1=0;<br /> TRISB2=0;<br /> TRISB4=1;<br /> TRISB5=1; //设置与键盘相关的各口的输入输出方式<br /> RB1=0;<br /> RB2=0; //设置扫描初始条件 <br />}<br />//spi方式显示初始化子程序<br />void SPIINIT()<br />{<br /> PIR1=0;<br /> SSPCON=0x30;<br /> SSPSTAT=0xC0;<br />//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送,与"74HC595,当其<br />//SCLK从低到高跳变时,串行输入寄存器"的特点相对应<br /> TRISC=0xD7; //SDO引脚为输出,SCK引脚为输出<br /> TRISA5=0; //RA5引脚设置为输出,以输出显示锁存信号<br />}<br />//I2C初始化子程序<br />void i2cint()<br />{<br /> SSPCON = 0X08; //初始化SSPCON寄存器<br /> TRISC3 =1; //设置SCL为输入口<br /> TRISC4 =1; //设置SDA为输入口<br /> TRISA4 = 0;<br /> SSPSTAT=0X80; //初始化SSPSTAT寄存器<br /> SSPADD=0X02; //设定I2C时钟频率<br /> SSPCON2=0X00; //初始化SSPCON2寄存器<br /> di(); //关闭总中断<br /> SSPIF=0; //清SSP中断标志<br /> RA4=0; //关掉74HC165的移位时钟使能,以免74HC165<br />//移位数据输出与I2C总线的数据线发生冲突<br /> SSPEN=1; //SSP模块使能<br />}<br />//软件延时子程序<br />void DELAY()<br />{<br /> for(i = 3553; --i ;) continue;<br />}<br />//键服务子程序<br />void keyserve()<br />{<br /> PORTB=0XFD ;<br /> if(RB5==0) BJF=0X01; //S9键按下,步进加标志置1<br /> PORTB=0XFB ;<br /> if(RB5==0) BJF=0X00; //S11键按下,步进加标志清0<br /> RB1=0; //恢复PORTB的值<br /> RB2=0;<br />}<br />//键扫描子程序<br />void KEYSCAN()<br />{<br />while(1){ <br />while(1) {<br /> if (RB5==0) break;<br /> }<br /> DELAY(); //若有键按下,则软件延时<br /> if (RB5==0) break; //若还有键按下,则终止循环扫描,返回<br /> }<br />}<br />//SPI传送数据子程序<br />void SPILED(data)<br />{<br /> SSPBUF=data; // 启动发送<br /> do {<br /> ;<br /> }while(SSPIF==0);<br /> SSPIF=0;<br />}<br />//显示子程序<br />void display()<br />{<br /> SPIINIT(); //spi方式显示初始化<br /> RA5=0; //准备锁存<br /> for(COUNTW=0;COUNTW<4;COUNTW++) {<br /> data=s[COUNTW];<br /> if(COUNTW==1) data=table0[data];//第二位需要显示小数点<br /> else data=table[data];<br /> SPILED(data); //发送显示段码<br /> }<br /> for(COUNTW=0;COUNTW<4;COUNTW++){<br /> data=0xFF;<br /> SPILED(data); //连续发送4个DARK,使显示看起来好看一些<br /> }<br /> RA5=1; //最后给一个锁存信号,代表显示任务完成<br />}<br />//I2C总线输出数据子程序<br />void i2cout()<br />{<br /> i2cint(); //因为SPI输出和I2C输出不能同时工作,则需要<br />//不断在两种方式见切换<br /> SEN=1; //产生I2C启动信号<br /> for(i=0x02;--i;) continue; //给予一定的延时,保证启动<br />do {<br /> RSEN=1; //产生I2C启动信号<br /> }while(SSPIF==0); //如果没能启动,则反复启动,直到启动为止<br /> SSPIF=0; //SSPIF标志清0<br /> SSPBUF=0X58; //I2C总线发送地址字节<br />do {<br /> ;<br /> }while(SSPIF==0); //等待地址发送完毕<br /> SSPIF=0; //SSPIF标志清0<br /> SSPBUF=0X01; //I2C总线发送命令字节<br />do {<br /> ;<br /> }while(SSPIF==0); //等待命令发送完毕<br /> SSPIF=0; //SSPIF标志清0<br /> SSPBUF=TXDATA; //I2C总线发送数据字节<br />do {<br /> ;<br /> }while(SSPIF==0); //等待数据发送完毕<br /> SSPIF=0; //SSPIF标志清0<br /> PEN=1; //产生停止条件<br />do {<br /> ;<br /> }while(SSPIF==0); //等待停止条件产生<br /> SSPIF=0; //SSPIF标志清0 <br />}<br />//步进加子程序<br />void BJADD()<br />{<br /> R1++;<br /> TXDATA=TXDATA+2;<br /> if(R1>9) {<br /> R1=0;<br /> R2++;<br /> if(R2>9) {<br /> R2=0;<br /> R3++;<br /> }<br /> }<br /> if((R3==1)&&(R2==2)&&(R1==1)){<br /> R3=0;<br /> R2=0;<br /> R1=0; //若R3,R2,R1超过120,则又从0计起<br /> TXDATA=0;<br /> }<br /> sfz(); //把需要显示的数字装入显示缓冲数组<br />}<br />//步进减子程序<br />void BJSUB()<br />{<br /> R1--;<br /> TXDATA=TXDATA-2;<br /> if(R1==0XFF) {<br /> R1=9;<br /> R2--;<br /> if(R2==0XFF) {<br /> R2=9;<br /> R3--;<br /> if(R3==0XFF) {<br /> R3=1;<br /> R2=2;<br /> R1=0; //若R3,R2,R1小于0,则又从120计起<br /> TXDATA=0XF0;<br /> }<br /> }<br /> }<br /> sfz(); //把需要显示的数字装入显示缓冲数组<br />}<br />//主程序<br />main()<br />{<br /> initial(); //系统各寄存器初始化<br /> display(); //调用一次显示子程序<br />while(1) {<br /> i2cout(); //调用I2C子程序,启动D/A转换 <br /> KEYSCAN(); //键盘扫描<br /> keyserve() ; //若确实有键按下,则调用键服务程序 <br /> if(BJF==0X01) BJADD();//若步进加标志为1,则调用步进加子程序<br /> else BJSUB(); //若步进加标志为0,则调用步进减子程序<br /> display(); //调用一次显示子程序<br />}<br />}<br /> |
|