国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

串口的基本知識你掌握了嗎 [復制鏈接]

發布時間:2018-10-19 15:49    發布者:wowo2018
在做項目的時候是不是發現串口是最常用的通信接口,所以我自己整理了一下關于串口的一些常識性知識,方便自己學習。
          關鍵詞:Loto虛擬示波器,串口時序,電平標準,模擬串口
    我們常說的串口按電平分類的話有兩種,一種是TTL電平的串口,一種是232電平的串口。
首先我們先看一下這兩種電平的區別。
TTL電平標準:輸出L:  <0.8V;  H: >2.4V,輸入L:  <1.2V:   H: >2.0V
TTL器件輸出低電平要小于0.8V,高電平要大于2.4V,輸入,低于1.2V就認為是0,高于2.0就認為是1.于是TTL電平的輸入低電平的噪聲容限就只有(O.8-0)/2=0.4V,高電平的噪聲容限為(5-2.4)/2=1.3V.
RS232標準:
邏輯1的電平為-3~-15V,輯0的電平為+3~+15V,注意電平的定義反相了一次。

   然而TTL電平的串口還可以分為兩種UART與USART。我們打開stm32cubeMX看到stm32F103有2個UART3個USART。在日常我們就可以說,它有5個串口,因為USART可以配置成UART

    UART與USART都是單片機上的串口通信,他們之間的區別如下:
首先從名字上看:
UART:universal asynchronous receiver and transmitter通用異步收/發器
USART:universal synchronous asynchronous receiver and transmitter通用同步/異步收/發器
  從名字上可以看出,USART在UART基礎上增加了同步功能,即USART是UART的增強型,事實也確實是這樣。但是具體增強到了什么地方呢?
  其實當我們使用USART在異步通信的時候,它與UART沒有什么區別,但是用在同步通信的時候,區別就很明顯了:大家都知道同步通信需要時鐘來觸發數據傳輸,也就是說USART相對UART的區別之一就是能提供主動時鐘。如STM32的USART可以提供時鐘支持ISO7816的智能卡接口。


     在實際的項目中用的最多的還是UART ,配置為:N, 8 ,1.波特率常用的有2400,9600,57600,115200.我們用串口來干什么呢?用過一些模塊的工程師會知道,很多模塊都是通過串口來控制或者通過串口透傳數據的,比如gsm(2g,4g),gps,wifi,藍牙等等,這些模塊都是通過串口來控制。所以作為一個工程師,必須要搞懂串口。下面我們通過Loto虛擬示波器采集不同波特率的UART 波形:

對比理論的時序圖,我們找找起始位和停止位,這個數據是多少?
有時候我們面試會考一個題目,那就是UART波特率9600的時候,它的一個bit是多長時間,這個怎么算?初學者肯定蒙了,我用串口直接就配置然后發數據就行了,從來沒算過,下面我總結一下:

波特率2400:1/2400416.67*10^(-6)s=416.67us
波特率4800:1/4800208.33*10^(-6)s=208.33us
波特率9600:1/9600104.17*10^(-6)s=104.17us
波特率19200:1/1920052.08*10^(-6)s=52.08us
波特率57600:1/5760017.36*10^(-6)s=17.36us
波特率115200:1/1152008.68*10^(-6)s=8.68us

對比我們用Loto虛擬示波器采集的數據看看是不是一致呢?


我們算這個數據有什么用呢?是的!沒錯!就是模擬串口!當單片機串口不夠用的時候項目中會用到。接下來我會分析幾個論友寫的代碼,逐步深入理解TTL串口。

下面這個模擬串口的代碼:
首先說它的發送吧,發送一個字節,先發送起始位OI_TXD = 0;  然后delay_us(BuadRate_9600);然后依次從低位開始檢測Data的每一位,從而拉高拉低OI_TXD,然后延時,移位,重復8次,最后發送停止位發送完一個Data
接收的話:它是stm32開了個定時器4和一個外部中斷.外部中斷采到下降沿,然后定時器設置為107us中斷一次,去采集一個bit,為什么是107us呢?因為此時波特率是9600,一個bit是104.17us,然后可以依次采集每個bit,直到采完一個data。(個人感覺107us不穩定)

  • /**
  • *軟件串口的實現(IO模擬串口)
  • * 波特率:9600    1-8-N
  • * TXD : PC13
  • * RXD : PB14
  • * 使用外部中斷對RXD的下降沿進行觸發,使用定時器4按照9600波特率進行定時數據接收。
  • * Demo功能: 接收11個數據,然后把接收到的數據發送出去
  • */
  • #define OI_TXD        PCout(13)
  • #define OI_RXD        PBin(14)
  • #define BuadRate_9600        100
  • u8 len = 0;        //接收計數
  • u8 USART_buf[11];  //接收緩沖區
  • enum{
  •         COM_START_BIT,
  •         COM_D0_BIT,
  •         COM_D1_BIT,
  •         COM_D2_BIT,
  •         COM_D3_BIT,
  •         COM_D4_BIT,
  •         COM_D5_BIT,
  •         COM_D6_BIT,
  •         COM_D7_BIT,
  •         COM_STOP_BIT,
  • };
  • u8 recvStat = COM_STOP_BIT;
  • u8 recvData = 0;
  • void IO_TXD(u8 Data)
  • {
  •         u8 i = 0;
  •         OI_TXD = 0;
  •         delay_us(BuadRate_9600);
  •         for(i = 0; i < 8; i++)
  •         {
  •                 if(Data&0x01)
  •                         OI_TXD = 1;
  •                 else
  •                         OI_TXD = 0;
  •                 delay_us(BuadRate_9600);
  •                 Data = Data>>1;
  •         }
  •         OI_TXD = 1;
  •         delay_us(BuadRate_9600);
  • }
  • void USART_Send(u8 *buf, u8 len)
  • {
  •         u8 t;
  •         for(t = 0; t < len; t++)
  •         {
  •                 IO_TXD(buf[t]);
  •         }
  • }
  • void IOConfig(void)
  • {
  •         GPIO_InitTypeDef  GPIO_InitStructure;
  •         NVIC_InitTypeDef NVIC_InitStructure;
  •          EXTI_InitTypeDef EXTI_InitStruct;
  •         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);         //使能PB,PC端口時鐘
  •          //SoftWare Serial TXD
  •         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  •         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽輸出
  •         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度為50MHz
  •         GPIO_Init(GPIOC, &GPIO_InitStructure);
  •         GPIO_SetBits(GPIOC,GPIO_Pin_13);
  •         //SoftWare Serial RXD
  •         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
  •         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  •         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  •         GPIO_Init(GPIOB, &GPIO_InitStructure);
  •         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
  •         EXTI_InitStruct.EXTI_Line = EXTI_Line14;
  •         EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
  •         EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿觸發中斷
  •         EXTI_InitStruct.EXTI_LineCmd=ENABLE;
  •         EXTI_Init(&EXTI_InitStruct);
  •         NVIC_InitStructure.NVIC_IRQChannel= EXTI15_10_IRQn ;
  •         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
  •         NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;
  •         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  •         NVIC_Init(&NVIC_InitStructure);
  • }
  • void TIM4_Int_Init(u16 arr,u16 psc)
  • {
  •         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  •         NVIC_InitTypeDef NVIC_InitStructure;
  •         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //時鐘使能
  •         //定時器TIM4初始化
  •         TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
  •         TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值
  •         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_tim
  •         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式
  •         TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位
  •         TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
  •         TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷
  •         //中斷優先級NVIC設置
  •         NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中斷
  •         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占優先級1級
  •         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //從優先級1級
  •         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  •         NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
  • }
  • int main(void)
  • {
  •          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優先級分組為組2:2位搶占優先級,2位響應優先級
  •          delay_init();
  •          IOConfig();
  •          TIM4_Int_Init(107, 71);         //1M計數頻率
  •         while(1)
  •         {
  •                 if(len > 10)
  •                 {
  •                         len = 0;
  •                         USART_Send(USART_buf,11);
  •                 }
  •         }
  • }
  • void EXTI15_10_IRQHandler(void)
  • {
  •         if(EXTI_GetFlagStatus(EXTI_Line14) != RESET)
  •         {
  •                 if(OI_RXD == 0)
  •                 {
  •                         if(recvStat == COM_STOP_BIT)
  •                         {
  •                                 recvStat = COM_START_BIT;
  •                                 TIM_Cmd(TIM4, ENABLE);
  •                         }
  •                 }
  •                 EXTI_ClearITPendingBit(EXTI_Line14);
  •         }
  • }
  • void TIM4_IRQHandler(void)
  • {
  •         if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
  •         {
  •                 TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
  •                  recvStat++;
  •                 if(recvStat == COM_STOP_BIT)
  •                 {
  •                         TIM_Cmd(TIM4, DISABLE);
  •                         USART_buf[len++] = recvData;
  •                         return;
  •                 }
  •                 if(OI_RXD)
  •                 {
  •                         recvData |= (1 << (recvStat - 1));
  •                 }else{
  •                         recvData &= ~(1 << (recvStat - 1));
  •                 }
  •   }
  • }


[color=rgb(51, 102, 153) !important]復制代碼

這里還有一個例子:
  • #include "stm32f10x.h"
  • #include "sys.h"
  • #include "exti.h"
  • #include "stdio.h"
  • //加入以下代碼,支持printf函數,而不需要選擇use MicroLIB
  • #if 1
  • #pragma import(__use_no_semihosting)
  • //標準庫需要的支持函數
  • struct __FILE
  • {
  •         int handle;
  • };
  • FILE __stdout;
  • //定義_sys_exit()以避免使用半主機模式
  • _sys_exit(int x)
  • {
  •         x = x;
  • }
  • //重定義fputc函數
  • int fputc(int ch, FILE *f)
  • {
  •     void SendOneByte(u8 Byte);
  •         SendOneByte((uint8_t) ch);
  •         return ch;
  • }
  • #endif
  • void SendOneByte(u8 Byte)
  • {
  •         u8 i=8,tmp;
  •         TXD_low(); //發送起始位
  •         delay_us(104);
  •         //發送8位數據
  •         for(i=0;i<8;i++)
  •         {
  •                 tmp        = (Byte >> i) & 0x01;  //低位在前
  •                 if(tmp == 0)
  •                 {
  •                         TXD_low();
  •                         delay_us(104);        //0
  •                 }
  •                 else
  •                 {
  •                         TXD_high();
  •                         delay_us(104);        //1
  •                 }
  •         }
  • //        while(i--)
  • //        {
  • //          MNUSART_TXD = (Byte&0x01);     //先傳低位
  • //          delay_us(104);
  • //          Byte = Byte>>1;
  • //          //無校驗位
  • //          MNUSART_TXD=1;//發送結束位
  • //          delay_us(104);
  • //        }
  •          TXD_high();
  •          delay_us(104);
  • }
  • void SendBytes(u8 *str,u8 len)        //發送數組最好用這個,也可發送字符串
  • {
  •   u16 i;
  •   for(i=0;i  {
  •            SendOneByte(str);
  •   }
  • }
  • void SendStr(u8 *str) //發送字符串,發送數組如果帶0x00就中斷發送了
  • {
  • while(*str)
  • SendOneByte(*str++);
  • }
  • int main(void)
  • {
  •   u8 len;
  •   u8 hello[]={0x5a,0xa5,0x00,0x00,0x01};
  •   delay_init();
  •   EXTIX_Init();
  •   //測試 發送一個字節
  •   SendOneByte(0x00);
  •   SendOneByte(0x01);
  •   SendOneByte(0x02);
  • //測試發送數組
  • SendBytes(hello,5);
  • //測試發送字符串
  • // SendBytes("hello word",11);
  • // SendStr("德瑪西亞");
  •   while(1)
  •         {
  •       if(USART_RX_STA&0x8000)
  •           {
  •              printf("\r\n您發送的消息為:\r\n\r\n");
  •                    len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度
  •                  SendBytes(USART_RX_BUF,len);
  •                  //也可以用下面的發送
  • //                 SendStr(USART_RX_BUF);
  • //                 for(len=0;len<200;len++)
  • //                 USART_RX_BUF[len]=0;
  •                    printf("\r\n\r\n");//插入換行
  •                 USART_RX_STA=0;
  •           }
  •         }
  • }


[color=rgb(51, 102, 153) !important]復制代碼

  • #include "exti.h"
  • #include "stm32f10x_gpio.h"
  • #include "stm32f10x_exti.h"
  • #include "sys.h"
  • u8 tmp;
  • u8 USART_RX_BUF[USART_REC_LEN];
  • u16 USART_RX_STA=0;
  • //extern SendOneByte(u8 Byte);
  • void EXTIX_Init(void)
  • {
  •                 GPIO_InitTypeDef GPIO_InitStructure;
  •                 EXTI_InitTypeDef EXTI_InitStructure;
  •                 NVIC_InitTypeDef NVIC_InitStructure;
  •                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
  •                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                 //PA.9 端口配置
  •                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽輸出
  •                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度為50MHz
  •                 GPIO_Init(GPIOA, &GPIO_InitStructure);                                         //根據設定參數初始化GPIOB.5
  •                 GPIO_SetBits(GPIOA,GPIO_Pin_9);
  •                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  •                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                          //浮空輸入
  •                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  •                 GPIO_Init(GPIOA, &GPIO_InitStructure);
  •                 GPIO_SetBits(GPIOA,GPIO_Pin_10);
  •                 //GPIOA.10 中斷線以及中斷初始化配置   下降沿觸發
  •                 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource10);
  •                 EXTI_InitStructure.EXTI_Line=EXTI_Line10;
  •                 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  •                 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  •                 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  •                 EXTI_Init(&EXTI_InitStructure);                 //根據EXTI_InitStruct中指定的參數初始化外設EXTI寄存器
  •                 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
  •                 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
  •                 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  •                 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  •                 NVIC_Init(&NVIC_InitStructure);
  • }
  • void EXTI15_10_IRQHandler(void)
  • {
  •    u8 i=9;
  •    if(EXTI_GetITStatus(EXTI_Line10) != RESET)
  •    {
  •                 /* Disable the Selected IRQ Channels -------------------------------------*/
  •                 NVIC->ICER[EXTI15_10_IRQn >> 0x05] =
  •                 (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
  •                 EXTI_ClearITPendingBit(EXTI_Line10);
  •                 delay_us(30);
  •                 while(i--)
  •                 {
  •                 tmp >>=1;
  •                 if(GPIOA->IDR&0x0400) tmp |=0x80;
  •                 delay_us(104);
  •         }
  •           if((USART_RX_STA&0x8000)==0)
  •           {
  •                         if(USART_RX_STA&0x4000)
  •                         {
  •                         if(tmp!=0x0a) USART_RX_STA=0;
  •                         else USART_RX_STA |=0x8000;
  •                         }
  •                         else
  •                         {
  •                         if(tmp==0x0d) USART_RX_STA|=0x4000;
  •                         else
  •                         {
  •                         USART_RX_BUF[USART_RX_STA&0X3FFF]=tmp ;
  •                         USART_RX_STA++;
  •                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收
  •                         }
  •                         }
  •           }
  •                 EXTI_ClearITPendingBit(EXTI_Line10);
  •                 NVIC->ISER[EXTI15_10_IRQn >> 0x05] =
  •                 (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
  •    }
  • }


本文地址:http://m.qingdxww.cn/thread-548609-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜影院黄| 日本三级韩国三级香港三的极不| 四虎成人免费网址在线| 精品手机在线1卡二卡3卡四卡| 欧美中文字幕| BL全肉多攻NP高H| 一级看片免费视频| 这里只有精品首页| 亚洲免费成人网| 一级a毛片免费观看久久精品| 夜夜操操| 亚洲经典在线观看| 人人上人人干| 午夜视频网站| 在线不卡中文字幕| 糖心在线观看| 亚洲精品久久久一区| 在线国产91| 天天摸夜添狠狠添高| 亚洲综合精品一二三区在线| 人妻熟女斩五十路0930 | 天堂在线xw| 久久视频这里只精品6国产| 三级黄色在线视频| 国内精品一级毛片免费看| 日本一本二本视频| 国产精品日本无码久久一老A| 奇米色888| 动漫H片在线播放免费高清| 欧美影视一区二区三区| qvod欧美电影| 亚洲综合色网| 99热这里只有精品6| 日韩在线视频一区| 97亚洲狠狠色综合久久久久| 日韩一级片免费在线观看| 中国性xxx免费视频| 欧美精品v欧洲精品| 在线亚洲天堂| 欧美成人h| 中文字幕一区二区三区在线不卡 |