娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

基于STM32的模擬UART串口通信工作原理

發(fā)布者:Yuexiang888最新更新時間:2024-03-21 來源: elecfans關(guān)鍵字:STM32  模擬UART  串口通信 手機(jī)看文章 掃描二維碼
隨時隨地手機(jī)看文章

UART工作原理

UART即通用異步收發(fā)器,是一種串行通信方式。數(shù)據(jù)在傳輸過程中是通過一位一位地進(jìn)行傳輸來實(shí)現(xiàn)通信的,串行通信方式具有傳輸線少,成本底等優(yōu)點(diǎn),缺點(diǎn)是速度慢。串行通信分為兩種類型:同步通信方式和異步通信方式。     但一般多用異步通信方式,主要因?yàn)榻邮芎桶l(fā)送的時鐘是可以獨(dú)立的這樣有利于增加發(fā)送與接收的靈活性。異步通信是一個字符接著一個字符傳輸,一個字符的信息由起始位、數(shù)據(jù)位、奇偶校驗(yàn)位和停止位組成。

每一個字符的傳輸靠起始位來同步,字符的前面一位是起始位,用下降沿通知收方開始傳輸,緊接著起始位之后的是數(shù)據(jù)位,傳輸時低位在前高位在后,字符本身由5~8位數(shù)據(jù)位組成。     數(shù)據(jù)位后面是奇偶校驗(yàn)位,最后是停止位,停止位是用高電平來標(biāo)記一個字符的結(jié)束,并為下一個字符的傳輸做準(zhǔn)備。停止位后面是不同長度的空閑位。停止位和空閑位都規(guī)定為高電平,這樣可以保證起始位有一個下降沿。     UART的幀格式如圖:

060885c6-3189-11ee-9e74-dac502259ad0.png

UART的幀格式包括線路空閑狀態(tài)(idle,高電平)、起始位(start bit,低電平)、5~8位數(shù)據(jù)位(data bits)、校驗(yàn)位(parity bit,可選)和停止位(stop bit,位數(shù)可為1、1.5、2位)。 

    

UART模擬原理


UART的模擬方式基本就是定時器+IO口實(shí)現(xiàn)。


方案1:只打印不接收


如果在實(shí)際使用中只是為了打印log而不接收數(shù)據(jù),可以采用DWT加普通IO口的方式;


#define  VCOM_BOUND     115200

#define  VCOM_PIN       GPIO_Pin_11

#define  VCOM_PORT      GPIOA

#define  VCOM_PIN_HIGH  VCOM_PORT->BSRR = VCOM_PIN

#define  VCOM_PIN_LOW   VCOM_PORT->BRR  = VCOM_PIN



#define  BSP_REG_DEM_CR                           (*(volatile unsigned int *)0xE000EDFC) //DEMCR寄存器

#define  BSP_REG_DWT_CR                           (*(volatile unsigned int *)0xE0001000)   //DWT控制寄存器

#define  BSP_REG_DWT_CYCCNT                       (*(volatile unsigned int *)0xE0001004) //DWT時鐘計(jì)數(shù)寄存器 

#define  BSP_REG_DBGMCU_CR                        (*(volatile unsigned int *)0xE0042004)



#define  DEF_BIT_00                               0x01u

#define  DEF_BIT_24                               0x01000000u

#define  BSP_BIT_DEM_CR_TRCENA                    DEF_BIT_24   

#define  BSP_BIT_DWT_CR_CYCCNTENA                 DEF_BIT_00

static unsigned int  sys_clock = 48000000;



inline void dwt_start(void)

{

 BSP_REG_DEM_CR     |= (unsigned int)BSP_BIT_DEM_CR_TRCENA;

    BSP_REG_DWT_CYCCNT  = (unsigned int)0u;            //初始化CYCCNT寄存器

    BSP_REG_DWT_CR     |= (unsigned int)BSP_BIT_DWT_CR_CYCCNTENA;    //開啟CYCCNT 

}



inline void dwt_stop(void)

{

 BSP_REG_DWT_CR = 0;

}



void vcom_pin_init(void)

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    GPIO_InitStructure.GPIO_Pin   = VCOM_PIN;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_Init(VCOM_PORT, &GPIO_InitStructure);

    GPIO_SetBits(VCOM_PORT,VCOM_PIN);

 VCOM_PIN_HIGH;

}



void vcom_put_char(char ch)

{

 int i;

 int dat[8];

 uint32_t sys_clk, bit_width;

 volatile uint32_t time_stamp;

 

    sys_clk = sys_clock/1000000;  

    bit_width = 1000000*sys_clk/VCOM_BOUND;

    for(i=0; i<8; i++)           

    {

        if(ch & 0x01)

            dat[i] = 1;

        else

            dat[i] = 0; 

        ch >>= 1;

    }

    OS_CPU_SR cpu_sr;

    enter_critical();//以下代碼進(jìn)行臨界保護(hù),防止被中斷打斷造成發(fā)送誤碼

    dwt_start();

    VCOM_PIN_LOW; //發(fā)送起始位

 time_stamp = BSP_REG_DWT_CYCCNT;

 while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width));

 for(i=0; i<8; i++)

 {

  if(dat[i])

   VCOM_PIN_HIGH;

  else

   VCOM_PIN_LOW;

  time_stamp = BSP_REG_DWT_CYCCNT;

  while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //發(fā)8bit 數(shù)據(jù)位

 }

 VCOM_PIN_HIGH;

 time_stamp = BSP_REG_DWT_CYCCNT;

 while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width));     //發(fā)停止位

 dwt_stop();

 exit_critical();

}



void vcom_printf(const char *fmt, ...)

{

    char buf[0x80];

    int  i;

    va_list ap;

 memset(buf, 0x00, sizeof(buf));

    va_start(ap, fmt);

    vsnprintf(buf, sizeof(buf), fmt, ap); 

    va_end(ap); 

 

 i = 0;

 while(buf[i])

 {

  vcom_put_char(buf[i]);

  i++;

 }

}

方案2:半雙工UART


實(shí)現(xiàn)方式: 普通定時器+普通IO口中斷+fifo


/**

*軟件串口的實(shí)現(xiàn)(IO模擬串口)

* 波特率:9600    1-8-N

* TXD : PC13

* RXD : PB14

* 使用外部中斷對RXD的下降沿進(jìn)行觸發(fā),使用定時器4按照9600波特率進(jìn)行定時數(shù)據(jù)接收。

* Demo功能: 接收11個數(shù)據(jù),然后把接收到的數(shù)據(jù)發(fā)送出去

*/



#define OI_TXD PCout(13)

#define OI_RXD PBin(14)



#define BuadRate_9600 100



u8 len = 0; //接收計(jì)數(shù)

u8 USART_buf[11];  //接收緩沖區(qū)



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; //下降沿觸發(fā)中斷

 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; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 

 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值

 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = Tck_tim

 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計(jì)數(shù)模式

 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時間基數(shù)單位

 TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);

 TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷

 

 //中斷優(yōu)先級NVIC設(shè)置

 NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中斷

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占優(yōu)先級1級

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //從優(yōu)先級1級

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

 NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器    

}

 

 

 int main(void)

 {  

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級分組為組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級

 delay_init();

 IOConfig();

 TIM4_Int_Init(107, 71);  //1M計(jì)數(shù)頻率

 

 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));

  } 

 }  

}


關(guān)鍵字:STM32  模擬UART  串口通信 引用地址:基于STM32的模擬UART串口通信工作原理

上一篇:基于STM32F407的USB轉(zhuǎn)串口功能實(shí)現(xiàn)
下一篇:stm32f407 easyflash移植過程記錄

推薦閱讀最新更新時間:2025-05-21 23:34

STM32串口通信詳解
一.數(shù)據(jù)通信方式 1.串行與并行通信 按數(shù)據(jù)傳送的方式,通訊可分為串行通訊與并行通訊。 串行通訊:是指設(shè)備之間通過一根數(shù)據(jù)信號線,地線以及控制信號線,按數(shù)據(jù)位形式一位一位地傳輸數(shù)據(jù)的通訊方式,同一時刻只能傳輸一位(bit)數(shù)據(jù)。 并行通訊:是指使用 8、16、32 及 64 根或更多的數(shù)據(jù)線(有多少信號為就需要多少信號位)進(jìn)行傳輸?shù)耐ㄓ嵎绞剑梢酝粫r刻傳輸多個數(shù)據(jù)位的數(shù)據(jù)。 串行通訊與并行通訊的特性對比: 并行可以同時發(fā)送多位數(shù)據(jù)所以速度比串行的速度要快很多,但并行要的數(shù)據(jù)線也更多相對成本會更高,而且并行傳輸對同步要求較高,且隨著通訊速率的提高,信號干擾的問題會顯著影響通訊性能。 2.全雙工、半雙工及單工通訊 單工通信:
[單片機(jī)]
<font color='red'>STM32</font><font color='red'>串口通信</font>詳解
STM32串口通信(一)
關(guān)于STM32串口通信USART的一些個人淺見: 1:對STM32中文數(shù)據(jù)手冊解讀之后,相信大家對USART串行通信有些了解,學(xué)習(xí)51的時候也都接觸過,使用串口只要弄明白原理就很簡單了 發(fā)送和接收數(shù)據(jù)的過程從圖上可以直觀的看出 USART串口通信涉及到幾個重要的寄存器 1:)狀態(tài)寄存器 2)數(shù)據(jù)寄存器 3)波特比率寄存器 例:若要設(shè)置比特率為9600,那么DIV就是468.75,則此寄存器的高12位應(yīng)存值:468,低4位存值:0.75*16=12(十進(jìn)制小數(shù)換算成十六進(jìn)制小數(shù));最后將整數(shù)和小數(shù)拼接:BRR=468 4+12;(詳細(xì)過程可參照源代碼;) 4)控制寄存器1: 5)控制寄存
[單片機(jī)]
<font color='red'>STM32</font><font color='red'>串口通信</font>(一)
STM32串口通信亂碼詳細(xì)處理方法
STM32串口通信以及溫度采集搞定,其中主要遇到STM32系列單片機(jī)時鐘樹的問題,串口通信遇到串口調(diào)試助手能夠接收到數(shù)據(jù)但出現(xiàn)亂碼現(xiàn)象,開始一直以為是串口配置和程序代碼問題,因?yàn)槭堑谝淮紊想娫诰€調(diào)試STM32板子,后面主要查串口波特率配置和收發(fā)函數(shù)程序段,如下圖: 波特率設(shè)置成115200沒問題,試著降低波特率改成9600和4800但問題依舊沒有解決,緊接著如下處理: 將重定向函數(shù)注釋,單獨(dú)寫串口發(fā)送字節(jié)和字符串函數(shù),依舊失敗。最后鎖定到系統(tǒng)時鐘配置上,由于手上的STM32開發(fā)板改用了12M的晶振,根據(jù)單片機(jī)時鐘樹的理解和解讀,一般采用外部時鐘HSE,系統(tǒng)時鐘配置成72M,8*9=72,,12*6=72,對于 SYSCLK、
[單片機(jī)]
基于STM32V評估板的嵌入式實(shí)時操作系統(tǒng)μC/OS-II串口通信設(shè)計(jì)
ARM是目前嵌入式領(lǐng)域中應(yīng)用最廣泛的RISC微處理器結(jié)構(gòu),以低成本、低功耗、高性能的特點(diǎn)占據(jù)了嵌入式系統(tǒng)應(yīng)用領(lǐng)域的領(lǐng)先地位,已遍及工業(yè)控制、消費(fèi)類電子產(chǎn)品、通信系統(tǒng)、網(wǎng)絡(luò)系統(tǒng)、無線系統(tǒng)等各類產(chǎn)品市場。STM32F103VB是基于ARM新內(nèi)核Cortex-M3的通用微處理器,STM32V評估板是基于該芯片的學(xué)習(xí)板并集成了仿真調(diào)試器(Ulink_Me),可以方便用戶快速學(xué)習(xí)和開發(fā)用戶程序。目前常見的嵌入式系統(tǒng)有:WinCE、Linux、pSoS、VxWorks和μC/OS-II等。μC/OS-Ⅱ是專門為嵌入式系統(tǒng)應(yīng)用設(shè)計(jì)的,具有源碼公開、實(shí)時性好、可移植裁剪、高效穩(wěn)定和教學(xué)科研免費(fèi)使用等特點(diǎn),已經(jīng)成功移植到8、16、32和64位等多種
[單片機(jī)]
基于STM32V評估板的嵌入式實(shí)時操作系統(tǒng)μC/OS-II<font color='red'>串口通信</font>設(shè)計(jì)
51單片機(jī)中斷系統(tǒng)(中斷系統(tǒng)原理,外部中斷,定時器中斷,串口通信)
自己整理的詳細(xì)知識點(diǎn),以后配置定時器中斷,串口通信不用再東找西找了。直接一文全打盡!!!因?yàn)閺腤ord直接復(fù)制過來圖片上傳不了,所以直接截圖上傳。
[單片機(jī)]
51單片機(jī)中斷系統(tǒng)(中斷系統(tǒng)原理,外部中斷,定時器中斷,<font color='red'>串口通信</font>)
51單片機(jī)—串口通信
. 串行通訊與并行通信 數(shù)字信號是八位二進(jìn)制數(shù),可以使用信號線傳輸,一種方案是使用一條數(shù)據(jù)線按照次序一位一位的傳送,每傳送完8位為一個字節(jié),這就是串行通信。還有一種方法是使用八條數(shù)據(jù)線同時傳送8個位的數(shù)據(jù),一次傳送一個字節(jié),這就是并行通信。 倆種通信方式圖示如下: 并行通信 特點(diǎn)為傳輸速度快,控制簡單,但遠(yuǎn)距離傳輸時成本較高且接收方同時接收各位比較難 串行通信 特點(diǎn)為傳輸線少,遠(yuǎn)距離傳輸時成本低,但數(shù)據(jù)傳輸比并行通信復(fù)雜 同步通信與異步通信 串行通信分為同步通信與異步通信 1.同步通信 顧名思義,同步通信就是對發(fā)送方和接收方的時鐘實(shí)行直接控制,使雙方的數(shù)據(jù)傳輸達(dá)到完全同步。數(shù)據(jù)以位的形式連續(xù)發(fā)送,且傳送的字符之
[單片機(jī)]
51單片機(jī)—<font color='red'>串口通信</font>
STM32F7xx —— 串口通信
一、串口初始化過程 1、時鐘使能; 2、GPIO初始化; 3、串口波特率設(shè)置; 4、串口控制; 5、數(shù)據(jù)發(fā)送與接收 二、幾個重要的串口函數(shù) HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); // 串口初始化 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); // 串口發(fā)送 HAL_StatusTypeDef HAL_UART_Receive(UART_Ha
[單片機(jī)]
單片機(jī)串口通信中斷
#include reg52.h //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 /*------------------------------------------------ 函數(shù)聲明 ------------------------------------------------*/ void SendStr(unsigned char *s); /*------------------------------------------------ 串口初始化 -----------------------------
[單片機(jī)]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 廉江市| 裕民县| 老河口市| 郓城县| 赫章县| 绥滨县| 庆安县| 广丰县| 岳普湖县| 舞钢市| 花莲市| 上高县| 祥云县| 靖江市| 承德县| 巩义市| 南雄市| 皋兰县| 鄂托克前旗| 汨罗市| 略阳县| 巴彦县| 泰安市| 巫溪县| 镇远县| 五峰| 苏尼特右旗| 固安县| 崇明县| 南郑县| 渝北区| 清涧县| 百色市| 凯里市| 邹平县| 射阳县| 报价| 苗栗县| 青龙| 万山特区| 曲麻莱县|