|
#i nclude //此程序實現"數控步進直流穩壓電源"的功能,調試時為了避免資源沖突,應使實驗板上 的拔碼開 關S8拔向高電平 //本程序設定S9鍵為增加鍵,當按住S9鍵不松開時,輸出Vout以0.1V連續步進, //直至鍵S9松開,當以一定的時間間隔點動S9鍵時,輸出Vout也為點動步進 //遞減鍵S11的功能與S9基本相同時,輸出電壓的值顯示在3個LED上 unsigned char R1,R2,R3,TXDATA,LEDF,BJF,COUNTW,data; unsigned int i; const char table[11]={0xc0,0xf9,0xa4,0xb0,0x99, 0x92, 0x82 ,0XD8,0x80,0x90,0xFF}; //不帶小數點的顯示段碼表 const char table0[11]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10, 0xFF}; //帶小數點的的顯示段碼表 unsigned char s[4]; //定義一個顯示緩沖數組 //把需要顯示的數字裝入顯示緩沖數組 void sfz() { s[0]=R3; s[1]=R2; s[2]=R1; s[3]=0x0A; //最后一個LED顯示"DARK" } //系統各寄存器初始化子程序 void initial() { R1=0X00; R2=0X00; R3=0X00; sfz(); //把需要顯示的數字裝入顯示緩沖數組 TXDATA=0X00; LEDF=0X01; BJF=0X01; TRISB1=0; TRISB2=0; TRISB4=1; TRISB5=1; //設置與鍵盤相關的各口的輸入輸出方式 RB1=0; RB2=0; //設置掃描初始條件 } //spi方式顯示初始化子程序 void SPIINIT() { PIR1=0; SSPCON=0x30; SSPSTAT=0xC0; //設置SPI的控制方式,允許SSP方式,并且時鐘下降沿發送,與"74HC595,當其 //SCLK從低到高跳變時,串行輸入寄存器"的特點相對應 TRISC=0xD7; //SDO引腳為輸出,SCK引腳為輸出 TRISA5=0; //RA5引腳設置為輸出,以輸出顯示鎖存信號 } //I2C初始化子程序 void i2cint() { SSPCON = 0X08; //初始化SSPCON寄存器 TRISC3 =1; //設置SCL為輸入口 TRISC4 =1; //設置SDA為輸入口 TRISA4 = 0; SSPSTAT=0X80; //初始化SSPSTAT寄存器 SSPADD=0X02; //設定I2C時鐘頻率 SSPCON2=0X00; //初始化SSPCON2寄存器 di(); //關閉總中斷 SSPIF=0; //清SSP中斷標志 RA4=0; //關掉74HC165的移位時鐘使能,以免74HC165 //移位數據輸出與I2C總線的數據線發生沖突 SSPEN=1; //SSP模塊使能 } //軟件延時子程序 void DELAY() { for(i = 3553; --i ;) continue; } //鍵服務子程序 void keyserve() { PORTB=0XFD ; if(RB5==0) BJF=0X01; //S9鍵按下,步進加標志置1 PORTB=0XFB ; if(RB5==0) BJF=0X00; //S11鍵按下,步進加標志清0 RB1=0; //恢復PORTB的值 RB2=0; } //鍵掃描子程序 void KEYSCAN() { while(1){ while(1) { if (RB5==0) break; } DELAY(); //若有鍵按下,則軟件延時 if (RB5==0)break; //若還有鍵按下,則終止循環掃描,返回 } } //SPI傳送數據子程序 void SPILED(data) { SSPBUF=data; // 啟動發送 do { ; }while(SSPIF==0); SSPIF=0; } //顯示子程序 void display() { SPIINIT(); //spi方式顯示初始化 RA5=0; //準備鎖存 for(COUNTW=0;COUNTW<4;COUNTW++) { data=s[COUNTW]; if(COUNTW==1) data=table0[data];//第二位需要顯示小數點 else data=table[data]; SPILED(data); //發送顯示段碼 } for(COUNTW=0;COUNTW<4;COUNTW++){ data=0xFF; SPILED(data); //連續發送4個DARK,使顯示看起來好看一些 } RA5=1; //最后給一個鎖存信號,代表顯示任務完成 } //I2C總線輸出數據子程序 void i2cout() { i2cint(); //因為SPI輸出和I2C輸出不能同時工作,則需要 //不斷在兩種方式見切換 SEN=1; //產生I2C啟動信號 for(i=0x02;--i;) continue; //給予一定的延時,保證啟動 do { RSEN=1; //產生I2C啟動信號 }while(SSPIF==0); //如果沒能啟動,則反復啟動,直到啟動為止 SSPIF=0; //SSPIF標志清0 SSPBUF=0X58; //I2C總線發送地址字節 do { ; }while(SSPIF==0); //等待地址發送完畢 SSPIF=0; //SSPIF標志清0 SSPBUF=0X01; //I2C總線發送命令字節 do { ; }while(SSPIF==0); //等待命令發送完畢 SSPIF=0; //SSPIF標志清0 SSPBUF=TXDATA; //I2C總線發送數據字節 do { ; }while(SSPIF==0); //等待數據發送完畢 SSPIF=0; //SSPIF標志清0 PEN=1; //產生停止條件 do { ; }while(SSPIF==0); //等待停止條件產生 SSPIF=0; //SSPIF標志清0 } //步進加子程序 void BJADD() { R1++; TXDATA=TXDATA+2; if(R1>9) { R1=0; R2++; if(R2>9) { R2=0; R3++; } } if((R3==1)&&(R2==2)&&(R1==1)){ R3=0; R2=0; R1=0; //若R3,R2,R1超過120,則又從0計起 TXDATA=0; } sfz(); //把需要顯示的數字裝入顯示緩沖數組 } //步進減子程序 void BJSUB() { R1--; TXDATA=TXDATA-2; if(R1==0XFF) { R1=9; R2--; if(R2==0XFF) { R2=9; R3--; if(R3==0XFF) { R3=1; R2=2; R1=0;//若R3,R2,R1小于0,則又從120計起 TXDATA=0XF0; } } } sfz(); //把需要顯示的數字裝入顯示緩沖數組 } //主程序 main() { initial(); //系統各寄存器初始化 display(); //調用一次顯示子程序 while(1) { i2cout(); //調用I2C子程序,啟動D/A轉換 KEYSCAN(); //鍵盤掃描 keyserve() ; //若確實有鍵按下,則調用鍵服務程序 if(BJF==0X01) BJADD();//若步進加標志為1,則調用步進加子程序 else BJSUB(); //若步進加標志為0,則調用步進減子程序 display(); //調用一次顯示子程序 } |