在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            基于STM32模擬UART串口通信

            作者: 時(shí)間:2024-12-27 來(lái)源:硬件筆記本 收藏

            工作原理

            即通用異步收發(fā)器,是一種串行通信方式。數(shù)據(jù)在傳輸過(guò)程中是通過(guò)一位一位地進(jìn)行傳輸來(lái)實(shí)現(xiàn)通信的,串行通信方式具有傳輸線少,成本底等優(yōu)點(diǎn),缺點(diǎn)是速度慢。串行通信分為兩種類型:同步通信方式和異步通信方式。

            本文引用地址:http://www.biyoush.com/article/202412/465846.htm

            但一般多用異步通信方式,主要因?yàn)榻邮芎桶l(fā)送的時(shí)鐘是可以獨(dú)立的這樣有利于增加發(fā)送與接收的靈活性。異步通信是一個(gè)字符接著一個(gè)字符傳輸,一個(gè)字符的信息由起始位、數(shù)據(jù)位、奇偶校驗(yàn)位和停止位組成。

            每一個(gè)字符的傳輸靠起始位來(lái)同步,字符的前面一位是起始位,用下降沿通知收方開(kāi)始傳輸,緊接著起始位之后的是數(shù)據(jù)位,傳輸時(shí)低位在前高位在后,字符本身由5~8位數(shù)據(jù)位組成。

            數(shù)據(jù)位后面是奇偶校驗(yàn)位,最后是停止位,停止位是用高電平來(lái)標(biāo)記一個(gè)字符的結(jié)束,并為下一個(gè)字符的傳輸做準(zhǔn)備。停止位后面是不同長(zhǎng)度的空閑位。停止位和空閑位都規(guī)定為高電平,這樣可以保證起始位有一個(gè)下降沿。

            的幀格式如圖:


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

            往期相關(guān)推文:串口通信基本原理

            UART模擬原理

            UART的模擬方式基本就是定時(shí)器+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時(shí)鐘計(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_00static 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;    //開(kāi)啟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)方式: 普通定時(shí)器+普通IO口中斷+fifo

            /**
            *軟件串口的實(shí)現(xiàn)(IO模擬串口)
            * 波特率:9600    1-8-N
            * TXD : PC13
            * RXD : PB14
            * 使用外部中斷對(duì)RXD的下降沿進(jìn)行觸發(fā),使用定時(shí)器4按照9600波特率進(jìn)行定時(shí)數(shù)據(jù)接收。
            * Demo功能: 接收11個(gè)數(shù)據(jù),然后把接收到的數(shù)據(jù)發(fā)送出去
            */#define OI_TXD PCout(13)#define OI_RXD PBin(14)#define BuadRate_9600 100u8 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端口時(shí)鐘 
             
             //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); //時(shí)鐘使能
             
             //定時(shí)器TIM4初始化
             TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值 
             TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
             TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
             TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計(jì)數(shù)模式
             TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
             TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
             TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷
             
             //中斷優(yōu)先級(jí)NVIC設(shè)置
             NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中斷
             NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占優(yōu)先級(jí)1級(jí)
             NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //從優(yōu)先級(jí)1級(jí)
             NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
             NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器    } 
             
             int main(void)
             {  
             NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級(jí)分組為組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
             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)鍵詞: UART 單片機(jī) STM32

            評(píng)論


            相關(guān)推薦

            技術(shù)專區(qū)

            關(guān)閉