小編今天筆記一下串口的收發實驗,實驗的靈感來源于對藍牙模塊收發的學習。我們在電路中使用藍牙,其實就是把藍牙看做是一個中轉站,這個中轉站在透傳的模式下,不會對接收到的數據做任何變動,而是直接轉發出去。
那么,我們只要知道單片機串口收發和PC端鍵盤的輸入都是以字符的ASCII碼的形式進行的,PC端收到后顯示則是正常字符的形式
即:
鍵盤鍵入字符(ASCII碼形式)–>單片機收到字符(ASCII碼形式)
敲擊3,實質鍵入0x33–>單片機讀buff收到消息0x33
單片機發送字符(ASCII嗎形式)–>模擬PC收到字符(正常形式顯示)
單片機發送字符3,實質寫buff發0x33–>模擬PC收到后顯示3 廢話少說,上仿真電路圖:
代碼: 仿真結果
鍵盤鍵入**.[ i]則
數碼管顯示*.*
PC端顯示**.*并換行循環顯示直至鍵入新的數
小編水平有限,有啥不對的地方,請路過的大佬指出。今天溜了。。。。 /*******個人之前的原創文章非抄襲*************/
- main.c
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define ulong unsigned long
- sbit LSA=P2^2;
- sbit LSB=P2^3;
- sbit LSC=P2^4; //38譯碼器的片選
- bit lanya = 0 ; //藍牙發送標志,單片機發送給PC
- uchar LanYa_DATA_count=0; //用于后面LnaYa_receive[]數組的各位數賦值,相當于中的i
- uchar LanYa_receive[4]; //LanYa串口接收數據緩存
- uint Receive_Data; //最后單片機接收的整合的數據 ,必須是uint,因為uchar不能超過255
- uchar Display_Data[3]; //處理要顯示在數碼管的數據緩沖數組
- uchar Computer[4]; //要發給PC的數組
- uchar T0RH = 0;//用于后面的TH0賦值
- uchar T0RL = 0;//用于后面的TL0賦值
- uchar UART_data;/*設一個中間變量,獲取讀sbuf的數據,在串口中斷服務函數中用到*/
- uchar code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79};
- /********************************************************
- 函數名稱:void delay(uint i)
- 函數作用:延時函數
- 參數說明:
- ********************************************************/
- void delay(uint i){ //延時函數
- while(i--);
- }
- /********************************************************
- 函數名稱:ConfigUart(uint baud)
- 函數作用:串口初始化函數
- 參數說明: baud:要設置的波特率
- ********************************************************/
- void ConfigUart(uint baud){
- SCON = 0x50; //配置串口:工作方式1,既可以接,也可以收
- TMOD |= 0x20; //配置定時器T1為工作方式2:自動重裝 ;使用T1的目的就是作為波特率發生去的一部分
- TH1 = 256 - (11059200/12/32)/baud; //利用公式,加上參數,計算T1重載值
- TL1 = TH1; //初值等于重載值
- ET1 = 0; //禁止定時器T1中斷(因為它作為波特發生器一部分)
- TR1 = 1; //啟動T1,即使能T1
- EA=1; //開總中斷
- ES=1; //開串行口中斷
- }
- /********************************************************
- 函數名稱:send_char_com(uchar ch)
- 函數作用:利用串口發送一個字符 ,串口接/收的其實就是8位的ASCII,即一個字符
- 參數說明: uchar ch:要發送的字符
- ********************************************************/
- void send_char_com(uchar ch) {
- SBUF=ch; //發sbuf,發送字符ch
- while(TI==0);//TI被硬件置1表示發送成功,跳出死循環
- TI=0; //軟件將TI置零,接著準備下次發送
- }
- /********************************************************
- 函數名稱:send_string_com(unsigned char *str,unsigned int strlen)
- 函數作用:利用串口發送字符串
- 參數說明: unsigned char *str:指針指向字符串的首地址,unsigned int strlen:想發送的長度(這個字符串的字符個數)
- ********************************************************/
- void send_string_com(uchar *str,uint strlen){
- uint k=0;
- do
- {
- send_char_com(*(str + k)); /*這里應該是用來指針的首地址+偏移量*/
- k++;
- }
- while(k < strlen);
- }
- /********************************************************
- 函數名稱:void ConfigTimer0(unsigned int ms)
- 函數作用:定時器0初始化函數,ms級定時溢出中斷
- 參數說明: unsigned int ms:設置定時溢出的ms數
- ********************************************************/
- void ConfigTimer0(uint ms){
- ulong tmp;
- tmp = 11059200/12;
- tmp = (tmp * ms)/1000;
- tmp = 65536 - tmp;
- tmp = tmp + 18;
- EA = 1;
- T0RH = (uchar)(tmp >> 8);
- T0RL = (uchar)tmp; //上面的這些行直接用就行
- TMOD &= 0xF0;
- TMOD |= 0x01; //設置TMOD的定時器0,方式1,需要重裝初值的
- TH0 = T0RH;
- TL0 = T0RL;
- ET0 = 1;//開定時器0的中斷允許
- TR0 = 1;//開定時器0的使能
- }
- /********************************************************
- 函數名稱:void dispiay()
- 函數作用:數據處理并顯示
- 參數說明: 無
- ********************************************************/
- void dispiay(){
- uchar i;
- Display_Data[0]=smgduan[Receive_Data/100];
- Display_Data[1]=smgduan[Receive_Data%100/10] | 0x80; //0x80是加個小數點
- Display_Data[2]=smgduan[Receive_Data%10];
- for(i=0;i<3;i++){ //先分別選中位,循環和switch實現
- switch(i){
- case 0: LSA=0;LSB=0;LSC=0;break;
- case 1: LSA=1;LSB=0;LSC=0;break;
- case 2: LSA=0;LSB=1;LSC=0;break;
- }
- P0=Display_Data[2-i]; //選中位后,傳段選數據
- delay(100); //延時1ms
- P0=0x00; //消隱
- }
- }
- /********************************************************
- 函數名稱:void main()
- 函數作用:數據處理并顯示
- 參數說明: 無
- ********************************************************/
- void main(){ //主程序
- uchar i;
- ConfigUart(9600); //波特率設置為9600
- ConfigTimer0(5); //定時器T0 5ms
- while(1){
- for(i=0;i<4;i++){
- Computer= LanYa_receive[ i];
- }
- dispiay();//顯示在數碼管
- f(lanya==1&&(UART_data=='\r')){//藍牙標志位置1,表單片機發送,并且讀buff收到回車字符(表示PC端發送結束)
- send_string_com(Computer,4); //將從PC端接收到的數據發送給PC端
- send_char_com('\r'); //發送\r,表換行
- lanya = 0; //藍牙標志清零,單片機發送結束
- }
- }
- }
- /********************************************************
- 函數名稱:void InterruptTimer0() interrupt 1
- 函數作用:定時器0中斷服務程序
- 參數說明: 無
- ********************************************************/
- void InterruptTimer0() interrupt 1{
- static uchar tmr1s = 0;
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- tmr1s++;
- if(tmr1s >= 200) //這個tmr1s變量起緩沖的
- {
- tmr1s = 0;
- lanya = 1; //將”lanya“標志位置1,準備在main中單片機發送數據
- }
- }
- /********************************************************
- 函數名稱:void uart(void) interrupt 4
- 函數作用:串口中斷服務程序
- 參數說明: 無
- ********************************************************/
- void uart(void) interrupt 4 {
- uchar a,b,c;
- if(RI)
- {
- UART_data=SBUF;
- f(UART_data=='\r'){ //如果檢測到回車按鍵則得到Receive_Data,將其(PC發送給單片機的數)通過display函數顯示在數碼管上
- a = LanYa_receive[0]-0x30;/*這些數都減0x30的原因是:微機原理中,數字0-9,對應ASCII嗎為30H-39H
- 字母A-Z 對應ASCII碼就是41H-5AH,字母a-z ASCII碼就是61H-7AH
- 這樣減30H就可以得到顯示正確的數字*/
- b = LanYa_receive[1]-0x30;
- c = LanYa_receive[3]-0x30;
- Receive_Data = a*100+b*10+c;
- LanYa_DATA_count=0;
- }
- else{ //否則將PC傳來的字符串一個字符一個字符的存放至LanYa_receive[]數組中
- LanYa_receive[LanYa_DATA_count]=UART_data;
- LanYa_DATA_count++;
- }
- }
- RI=0;
- }
- /******************************************************/
復制代碼
|