- #include<STC12C5A60S2.h>
- //單片機頭文件,儲存一些殊寄存器的地址聲明
- #include<intrins.h>
- //intrins頭文件儲存51編程中需要使用到空指令_nop_()、字符循環移位指令_crol_等
- #include <stdio.h>
- //stdio : "standard input & output"(標準輸入輸出),C/C++頭文件,把多個編譯單元(.c或者.cpp文件)公用的內容,單獨放在一個文件里減少整體代碼尺寸
- #define usint unsigned short int //符號短整型
- #define uchar unsigned char //無符號字符型
- #define uint unsigned int //無符號整型
- #define VALID 0 //0
- #define INVALID 1 //1
- #define LCD_data P0 //LCD數據端口P0
- sbit LCD_RS = P2^7; //LCD命令和數據控制位,1:寫數據位,0:寫命令
- sbit LCD_RW = P2^6; //LCD讀寫控制位
- sbit LCD_EN = P2^5; //LCD使能位
- sbit IN1 = P2^0; //電機
- sbit IN2 = P2^1;
- sbit ENA = P2^3;
- uchar code title2[] = {"電機轉速:"};
- uchar code ascii[] =
- {0x31,0x32,0x33,0x41,0x34,0x35,0x36,0x42,0x37,0x38,0x39,0x43,0x2A,0x30,0x23,0x44}; //數字和常用字符的ascii碼
- uint n = 0; //T0定時中斷響應次數
- uint n_pwm = 0; //用于調節pwm占空比
- uint c = 0; //外部計數中斷響應次數
- uint flag_T0 = 0; //定時器T0溢出flag
- uchar th = 0; //脈沖計數計算時的臨時變量高位
- uchar tl = 0; //……………………………………………低位
- uint num_pulse; //脈沖個數
- void delay_1ms(uint z){ //延時函數1ms
- uint x,y;
- for(x = z; x > 0; x--)
- for(y = 920; y > 0; y--);
- }
- void write_cmd(uchar cmd){ //LCD寫命令函數
- LCD_RS = 0;
- LCD_RW = 0;
- LCD_EN = 0;
- P0 = cmd;
- delay_1ms(6);
- LCD_EN = 1;
- delay_1ms(6);
- LCD_EN = 0;
- }
- void write_dat(uchar dat){ //LCD寫數據函數
- LCD_RS = 1;
- LCD_RW = 0;
- LCD_EN = 0;
- P0 = dat;
- delay_1ms(5);
- LCD_EN = 1;
- delay_1ms(5);
- LCD_EN = 0;
- }
- void lcd_pos(uchar X,uchar Y){ //X表示LCD的行數,Y表示LCD的列數
- uchar pos;
- if(X == 0){
- X = 0x80;
- }
- else if(X == 1){
- X = 0x90;
- }
- else if(X == 2){
- X = 0x88;
- }
- else if (X == 3){
- X = 0x98;
- }
- pos = X+Y ;
- write_cmd(pos); //顯示地址
- }
- void lcd_init(){
- uchar i = 0;
- write_cmd(0x30); //基本指令操作
- delay_1ms(5);
- write_cmd(0x0C); //顯示開,關光標
- delay_1ms(5);
- write_cmd(0x01); //清除LCD的顯示內容
- delay_1ms(5);
- lcd_pos(0,0); //將LCD光標定位到第一行第一列
- }
- void pulse_dispaly(uint fe) //顯示脈沖個數
- {
- uchar i = 0;
- uchar f[7];
- for(i = 0; i < 7; i++)
- f[i] = '0';
- f[0] = ((fe)/100000) +0x30;//十萬位的數字
- f[1] = ((fe)%100000)/10000 +0x30;//萬位的數字
- f[2] = ((fe)%10000)/1000 +0x30;//千位的數字
- f[3] = ((fe)%1000 )/100 +0x30;//百位的數字
- f[4] = ((fe)%100 )/10 +0x30;//十位的數字
- f[5] = ((fe)%10 ) +0x30;//個位的數字
- f[6] = '\0';
- i = 0;
- lcd_pos(1,5); //將光標定位到第2行第6列開始顯示
- while(f[i] != '\0'){
- write_dat(f[i]);
- i++;
- }
- }
- void display_text(int pos, uchar *text){ //顯示一段字text、pos設置在第幾行開頭顯示
- uchar j;
- lcd_pos(pos,0);
- while(text[j]!='\0'){
- write_dat(text[j]);
- j++;
- }
- j=0;
- }
- void INIT(){ //初始化函數
- TMOD = 0X51; //定時器初始化0101_0001
- TH0 = (65536-922)/256; //定時器初值(1ms),0.001s/(1.085*10^(-6))s=922
- TL0 = (65536-922)%256;
- TH1 = 0X00; //計數器初值
- TL1 = 0x00;
- ET0 = 1; //允許中斷T0
- ET1 = 1;
- EA = 1; //總中斷開放
- TR0 = 1; //啟動T0
- TR1 = 1; //啟動T1
- IN2 = 0; //電機初始化
- IN1 = 1;
- ENA = 0;
- }
- void main(){
- uchar i;
- INIT();
- lcd_init(); //LCD初始函數
- display_text(1, title2); //在第2行開頭顯示 "電機轉速:"
- while(1){
- if (flag_T0 == 1){ //1s
- /*脈沖計數(電機轉速通過脈沖個數的方式輸出)*/
- th = TH1; //用臨時變量讀取計數器數值
- tl = TL1;
- num_pulse = th*256 + tl; //計數器16進制轉10進制
- TH1 = 0X00; //重新賦計數器的值
- TL1 = 0x00;
- pulse_dispaly(num_pulse); //循環調用顯示函數
- th = 0;
- tl = 0;
- /*脈沖計數*/
- flag_T0 = 0;
- }
- }
- }
- void interrupt_Timer0() interrupt 1 { //定時器中斷(1ms)
- TR0 = 0;
- TH0 = (65536-922)/256; //重新賦初值
- TL0 = (65536-922)%256;
- n++;
- n_pwm++; //一個pwm脈沖周期為10ms,速度10檔可調
- ENA = 1;
- if (n_pwm > 10) //超過一個pwm周期
- n_pwm = 1;
- if (n_pwm <= 5) //占空比50%
- IN1 = 1; //pwm高電平
- else
- IN1 = 0; //pwm低電平
-
- if(n == 1000){ //計滿1s
- flag_T0 = 1;
- n = 0;
- }
- TR0 = 1;
- }
- void interrupt_Timer1() interrupt 3 { //計數器中斷
- TR1 = 0;
- TH1 = 0x00; //重新賦值
- TL1 = 0x00;
- TR1 = 1;
- }
復制代碼
|