文件夾 e:\dpj\20210101
目標 STC15W4K32S4
proteus 新建單片機 串口 分壓調節電壓源 更改單片機主頻為11059200
虛擬串口軟件安裝及配置
單片機使用COM4 串口調試器使用COM3 波特率 115200
ADC讀取電壓數據正常 P1.0 P1.1
串口通訊測試正常 ADC 通過可變電阻調節電壓后 模擬量變化發送串口
串口通訊測試正常 中斷接收<>之間字符,回送 因地址空間,字符個數<10
程序運行時間以protues左下角的運行時間為準 見截圖
定時器設置及中斷處理 以1ms為周期,每3000ms在串口發送字符
串口命令設置定時器發送數據到串口的時間間隔 <后的第一個字符為A 第二個為數字 表示間隔秒數
仿真原理圖如下(STC15W4K32S4單片機proteus仿真工程文件可到本帖附件中下載)
單片機源程序如下:
- /*---------------------------------------------------------------------*/
- /* --- STC MCU Limited ------------------------------------------------*/
- /* --- STC15F4K60S4 系列 定時器1用作串口1的波特率發生器舉例------------*/
- /* 如果要在程序中使用此代碼,請在程序中注明使用了STC的資料及程序 */
- /* 如果要在文章中應用此代碼,請在文章中注明使用了STC的資料及程序 */
- /*---------------------------------------------------------------------*/
- //本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
- //若無特別說明,工作頻率一般為11.0592MHz
- #include "STC15Fxxxx.H"
- //#include "reg51.h"
- #include <stdio.h>
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- //typedef unsigned int u16; //對數據類型進行聲明定義
- //typedef unsigned char u8;
- #define FOSC 11059200L //系統頻率
- #define BAUD 115200 //串口波特率
- #define NONE_PARITY 0 //無校驗
- #define ODD_PARITY 1 //奇校驗
- #define EVEN_PARITY 2 //偶校驗
- #define MARK_PARITY 3 //標記校驗
- #define SPACE_PARITY 4 //空白校驗
- #define PARITYBIT NONE_PARITY //定義校驗位
- /* STC15Fxxxx.H中已定義
- //sfr P0M1 = 0x93;
- //sfr P0M0 = 0x94;
- //sfr P1M1 = 0x91;
- //sfr P1M0 = 0x92;
- //sfr P2M1 = 0x95;
- //sfr P2M0 = 0x96;
- //sfr P3M1 = 0xb1;
- //sfr P3M0 = 0xb2;
- //sfr P4M1 = 0xb3;
- //sfr P4M0 = 0xb4;
- //sfr P5M1 = 0xC9;
- //sfr P5M0 = 0xCA;
- //sfr P6M1 = 0xCB;
- //sfr P6M0 = 0xCC;
- //sfr P7M1 = 0xE1;
- //sfr P7M0 = 0xE2;
- //sfr AUXR = 0x8e; //輔助寄存器
- //sfr P_SW1 = 0xA2; //外設功能切換寄存器1
- */
- #define S1_S0 0x40 //P_SW1.6
- #define S1_S1 0x80 //P_SW1.7
- #define ADC_POWER 0x80 //ADC電源控制位
- #define ADC_FLAG 0x10 //ADC完成標志
- #define ADC_START 0x08 //ADC起始控制位
- #define ADC_SPEEDLL 0x00 //540個時鐘
- #define ADC_SPEEDL 0x20 //360個時鐘
- #define ADC_SPEEDH 0x40 //180個時鐘
- #define ADC_SPEEDHH 0x60 //90個時鐘
- //sbit P22 = P2^2;
- unsigned int ch;a,b;
- unsigned int dd=0;
- unsigned int cc=0;
- unsigned int cc0=0;
- unsigned int cc1=0;
- unsigned int cc00=0;
- unsigned int cc01=0;
- unsigned int cc10=0;
- unsigned int cc11=0;
- unsigned int time0count0 = 0 ;
- unsigned int time0count1 = 0 ;
- unsigned int time0count = 3000 ;
- bit busy;
- char receivechar = 0;
- int receive_count = 0;
- int received = 0;
- WORD receivestr[10];
- void InitUart();
- void InitADC();
- void Timer0Init();
- void SendData(BYTE dat);
- void SendString(char *s);
- void serial_put_uint(unsigned int number);
- void Delay(WORD n);
- //void ShowResult(BYTE ch);
- unsigned int GetADCResultint(BYTE ch);
- void main()
- {
- int initreceivestrcount=0;
- unsigned int tt0=0,tt1=0;
- // unsigned int d1,d2,d3,i;
- unsigned int i=0;
- if (i == 0 ) //初始化tt0 tt1 P0 -P7 數據
- {
- /*
- 例如將P1M0=0X60和P1M1=0X00譯成bai二進制代碼是
- P1M0=0110 0000,duP1M1=0000 0000.
- 按照I/O口工作模式設置zhi規定
- 都為0時為準雙向口(dao傳統8051單片機zhuanI/O口模式)
- 為0,1時為推挽(shu強上拉輸出),
- 為1,0時為高阻(僅輸入),
- 為1,1時為開漏(內部上拉斷開,須外加上拉電阻)
- 你選擇的是P1M0和P1M1所以針對的是P1口的操作,
- 將兩個二進制代碼一位位的比較可知:P1.0~P1.4及P1.7都為0,
- 故這些I/O口設置的是標準狀態;P1.5和P1.6為高阻態
- (P1M0上的第六位和第七位都為1,P1M1上的第六位和第七位都是0。1,0時為高阻)
- */
- tt0=16640;
- tt1=tt0/256;
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x03;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P6M0 = 0x00;
- P6M1 = 0x00;
- P7M0 = 0x00;
- P7M1 = 0x00;
- }
- InitUart(); //初始化串口
- //printf ("20200102 第一次調試 a 1 取左字節 a %d A/256=A %d C51\n" , tt0,tt1 ); /* ?? "Hello C51 " */
- SendString("20200102 第二次調試 \r\n");
- initreceivestrcount=0;
- while (initreceivestrcount<10) //初始化 receivestr
- {
- receivestr[initreceivestrcount]=0;
- initreceivestrcount = initreceivestrcount + 1 ;
- }
- //printf ("Hello"); //printf 不能使用 編譯通過 不能仿真運行
- InitADC(); //初始化ADC
- Timer0Init(); //定時器0初始化
- /* 除法測試
- //printf ("Hello ADC 第y次調試 a 1 加代碼a %d A/256=A %d C51\n" , tt0,tt1 );
- // sprintf(str," receive %d \r\n",receivechar);
- // SendString(str);
- // sprintf(str," d1 %d a \r\n",tt0);
- // SendString(str);
- // sprintf(str," d2 %d a \r\n",tt1);
- // SendString(str);
- // sprintf(str," d3 %d a \r\n",d3);
- // SendString(str);
- */
- SendString("c STC15W4kS32\r\n Uart Test !\r\n");
- while(1)
- {
- if (received == 1) // 在串口接收預定義字符后回送 20210103 增加控制定時顯示功能
- {
- /* 除法測試及sprintf
- // SendString("\r\n");
- // d1 = receivechar;
- // d2 = d1 ;
- // d3=d2*256;
- // d3=d1-d3;
- // sprintf(str," receive %d a\r\n",receivechar);
- // SendString(str);
- // sprintf(str," d1 %d b \r\n",d1);
- // SendString(str);
- // sprintf(str," d2 %d c \r\n",d2);
- // SendString(str);
- // sprintf(str," d3 %d d \r\n",d3);
- // SendString(str);
- // SendString(receivestr);receivechar
- */
- serial_put_uint(receivechar);
- SendString(" start ");
- //serial_put_uint(11);
- for (i=0;i<receive_count;i++)
- {
- SendData(receivestr[i]);
- }
- SendString(" COUNT= ");
- serial_put_uint(receive_count);
- receive_count = 0 ;
- if (receivestr[1] == 65 )
- {
- time0count = ( receivestr[2] - 48 ) * 1000 ;
- SendString(" \r\n 串口設定 time0 ");
- serial_put_uint(time0count/1000);
- SendString(" 秒定時 ");
- }
- SendString(" \r\n");
- received = 0 ;
- }
- if (time0count0 != time0count1) // 串口設定的秒定時
- {
- SendString(" time0 ");
- serial_put_uint(time0count/1000);
- SendString(" 秒定時 執行 ");
- serial_put_uint(time0count0);
- SendString(" \r\n ");
- time0count1 = time0count0;
- }
- b=b+1;
- dd=0;
- cc00 = GetADCResultint(dd); //讀取ADC 0 P1.0 數據
- if (cc01 != cc00) // ADC 0 P1.0 數據變化發送串口
- {
- SendString(" ADC ");
- // serial_put_uint(b);
- SendString(" ch ");
- serial_put_uint(dd);
- SendString(" new ");
- serial_put_uint(cc00);
- SendString(" old ");
- serial_put_uint(cc01);
- SendString(" end \r\n");
- //printf (" ADC %d ch %d :0x %x 0d %d \n", b,dd,cc00,cc01 );
- cc01 = cc00;
- }
- dd=1;
- cc10 = GetADCResultint(dd); //讀取ADC 1 P1.1 數據
- if (cc11 != cc10) // ADC 1 P1.1 數據變化發送串口
- {
- SendString(" ADC ");
- // serial_put_uint(b);
- SendString(" ch ");
- serial_put_uint(dd);
- SendString(" new ");
- serial_put_uint(cc10);
- SendString(" old ");
- serial_put_uint(cc11);
- SendString(" end \r\n");
- //printf (" ADC %d ch %d :0x %x 0d00 %d \n", b,dd,cc10,cc11 );
- cc11=cc10;
- }
- dd=0;
- if (b>10000) b=0;
- }
- }
- /*******************************************************************************
- * 函 數 名 : Timer0Init
- * 函數功能 : 定時器0初始化
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void Timer0Init()
- {
- TMOD|=0X01;//選擇為定時器0模式,工作方式1,僅用TR0打開啟動。
- TH0=0XFC; //給定時器賦初值,定時1ms
- TL0=0X18;
- ET0=1;//打開定時器0中斷允許
- EA=1;//打開總中斷
- TR0=1;//打開定時器
- }
- /*----------------------------
- 初始化串口
- ----------------------------*/
- void InitUart()
- {
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
- // P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
-
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=1 S1_S1=0
- // ACC |= S1_S0; //(P3.6/RxD_2, P3.7/TxD_2)
- // P_SW1 = ACC;
- //
- // ACC = P_SW1;
- // ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=1
- // ACC |= S1_S1; //(P1.6/RxD_3, P1.7/TxD_3)
- // P_SW1 = ACC;
- #if (PARITYBIT == NONE_PARITY)
- SCON = 0x50; //8位可變波特率
- #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
- SCON = 0xda; //9位可變波特率,校驗位初始為1
- #elif (PARITYBIT == SPACE_PARITY)
- SCON = 0xd2; //9位可變波特率,校驗位初始為0
- #endif
- AUXR = 0x40; //定時器1為1T模式
- TMOD = 0x00; //定時器1為模式0(16位自動重載)
- TL1 = (65536 - (FOSC/4/BAUD)); //設置波特率重裝值
- TH1 = (65536 - (FOSC/4/BAUD))>>8;
- TR1 = 1; //定時器1開始啟動
- ES = 1; //使能串口中斷
- EA = 1;
-
-
-
- // SCON = 0x5a; //設置串口為8位可變波特率
- //#if URMD == 0
- // T2L = (65536 - (FOSC/4/BAUD));
- // T2H = (65536 - (FOSC/4/BAUD)) >> 8;
- // AUXR = 0x14; //T2為1T模式, 并啟動定時器2
- // AUXR |= 0x01; //選擇定時器2為串口1的波特率發生器
- //#elif URMD == 1
- // AUXR = 0x40; //定時器1為1T模式
- // TMOD = 0x00; //定時器1為模式0(16位自動重載)
- // TL1 = (65536 - (FOSC/4/BAUD));
- // TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
- // TR1 = 1; //定時器1開始啟動
- //#else
- // TMOD = 0x20; //設置定時器1為8位自動重裝載模式
- // AUXR = 0x40; //定時器1為1T模式
- // TH1 = TL1 = (256 - (FOSC/32/BAUD));
- // TR1 = 1;
- //#endif
- }
- /*----------------------------
- 初始化ADC
- ----------------------------*/
- void InitADC()
- {
- P1M0 =1;
- P1M1 =0;
- P1 = 0Xff;
- P1ASF = 0xff; //設置P1口為AD口
- ADC_RES = 0; //清除結果寄存器
- ADC_RESL = 0; //清除結果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- Delay(2); //ADC上電并延時
- }
- /*----------------------------
- 讀取ADC結果 20210101 注釋GetADCResult 用GetADCResultint代替
- ----------------------------*/
- unsigned int GetADCResultint(BYTE ch)
- {
- unsigned int ret=0;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //等待4個NOP
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG));//等待ADC轉換完成
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
- ret = ADC_RES*4 + ADC_RESL;
- return ret; //返回ADC結果
- }
- /*----------------------------
- UART 中斷服務程序
- -----------------------------*/
- void Uart() interrupt 4
- {
- if (RI)
- {
- RI = 0; //清除RI位
- receivechar = SBUF; //P0顯示串口數據
- if ( receivechar == 60 ) receive_count = 0 ;
- if ((receive_count<9) && ( receivechar != 62 )&&(received == 0 ))
- {
- receivestr[receive_count] = receivechar;
- receivestr[receive_count+1] = 0;
- receive_count = receive_count + 1 ;
-
- }
- else
- {
- received = 1;
- // while (initreceivestrcount<10)
- // {
- // receivestr[initreceivestrcount]=0;
- // initreceivestrcount = initreceivestrcount + 1 ;
- // }
-
- }
- // SendData(receivechar);
- // P22 = RB8; //P2.2顯示校驗位
- }
-
- if (TI)
- {
- TI = 0; //清除TI位
- busy = 0; //清忙標志
- }
- }
- void Timer0() interrupt 1
- {
- static u16 itime0;
- TH0=0XFC; //給定時器賦初值,定時1ms
- TL0=0X18;
- itime0++;
- if(itime0==time0count)
- {
- itime0=0;
- time0count0 = time0count0 + 1;
- if ( time0count0 > 20 ) time0count0 = 0;
- }
- }
- /*----------------------------
- 發送串口數據
- ----------------------------*/
- void SendData(BYTE dat)
- {
- while (busy); //等待前面的數據發送完成
- ACC = dat; //獲取校驗位P (PSW.0)
- // if (P) //根據P來設置校驗位
- // {
- //#if (PARITYBIT == ODD_PARITY)
- // TB8 = 0; //設置校驗位為0
- //#elif (PARITYBIT == EVEN_PARITY)
- // TB8 = 1; //設置校驗位為1
- //#endif
- // }
- // else
- // {
- //#if (PARITYBIT == ODD_PARITY)
- // TB8 = 1; //設置校驗位為1
- //#elif (PARITYBIT == EVEN_PARITY)
- // TB8 = 0; //設置校驗位為0
- //#endif
- // }
- busy = 1;
- SBUF = ACC; //寫數據到UART數據寄存器
- }
- /*----------------------------
- 發送字符串
- ----------------------------*/
- void SendString(char *s)
- {
- // EA = 0 ;
- // ES = 0 ;
- while (*s) //檢測字符串結束標志
- {
- SendData(*s++); //發送當前字符
- }
- // EA = 1 ;
- // ES = 1 ;
- }
- void serial_put_uint(unsigned int number)
- {
- unsigned int i;
- unsigned int nTmp;
- // *s++ =num/10 +'0';
- //*s++=num%10 +'0';
- //*s =0;
-
- //感覺這寫法怪怪的嗎?干嘛不for(i=1;i<5;i++) 因為這樣不需要使用庫函數pow()
- for(i=10000;i>=1;i=i/10)
- {
- nTmp = number/i;
- if(nTmp >=1 ) SendData((unsigned char)(nTmp%10 + 0x30));
- }
- }
- /*----------------------------
- 軟件延時
- ----------------------------*/
- void Delay(WORD n)
- {
- WORD x;
- while (n--)
- {
- x = 5000;
- while (x--);
- }
- }
復制代碼
所有資料51hei提供下載:
20210103a.rar
(580.92 KB, 下載次數: 243)
2021-1-3 13:45 上傳
點擊文件名下載附件
|