1、添加頭文件
首先我們先添加相應(yīng)的頭文件。既然我們要進行對串口的模擬,因此我們要先了解uart相關(guān)的通信協(xié)議。由于UART的通信方式是由1個起始位,8個數(shù)據(jù)位,包含一個奇偶校驗位,和結(jié)束位構(gòu)成因此我們將使用單片機中的兩個普通的IO口電平的高低進行對相應(yīng)時序的模擬。
#include"stm32f10x.h" #include"vuart2.h"
2、宏定義
使用到的io口為
#defineOI2_TXDPDout(6) #defineOI2_RXDPDin(7) #defineBuadRate2_9600104 #defineRecive2_Byte19//接收緩沖器的個數(shù) u8len2=0;//接收計數(shù) u8USART2_buf[Recive2_Byte];//接收緩沖區(qū)
將IO口相應(yīng)的位帶操作函數(shù)進行宏定義從而使得在對不同的電平的進行轉(zhuǎn)換的時候更為方便,并且減少了調(diào)用其他函數(shù)的過程所消耗的時間,程序執(zhí)行效率更高。
在本次的傳輸過程中我選用的是使用波特率速率為9600,也就是1s中發(fā)送9600個字節(jié),因此對每個字節(jié)數(shù)據(jù)進行計算1000000us/9600可以得出,發(fā)一個字節(jié)的數(shù)據(jù)需要進行大概需要 104.16us并且對于相應(yīng)的電平持續(xù)時間要求誤差不能超過±5%因此對我們進行時間的控制要求就顯得比較重要了。
3、枚舉出各個位
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, }; u8recvStat2=COM_STOP_BIT; u8recvData2=0;
4、IO——TXD進行模擬
voidIO2_TXD(u8Data) { u8i=0; OI2_TXD=0; delay_us(BuadRate2_9600); for(i=0;i8;?i++) ????{ ????????if(Data&0x01) ????????????OI2_TXD?=?1;?? ????????else ????????????OI2_TXD?=?0;?? ???????? ????????delay_us(BuadRate2_9600); ????????Data?=?Data>>1; } OI2_TXD=1; delay_us(BuadRate2_9600); }
由于發(fā)送的信號是將TXD信號進行拉低處理,因此在拉低TXD相應(yīng)的IO口之后進行延時處理,再進行循環(huán)對我們需要發(fā)送的各個位的數(shù)據(jù)繼續(xù)進行發(fā)送循環(huán)發(fā)送完成之后將電平拉高代表停止位。
5、構(gòu)建發(fā)送函數(shù)
voidUSART2_Send(u8*buf,u8len2) { u8t; for(t=0;t
其中的*buf為需要發(fā)送的數(shù)據(jù),len2為數(shù)據(jù)長度,進行循環(huán)調(diào)用IO_TXD進行一個字節(jié)一個字節(jié)的數(shù)據(jù)發(fā)送。
6、IO口初始化
voidIO2Config(void) { GPIO_InitTypeDefGPIO_InitStructure;//初始化gpio NVIC_InitTypeDefNVIC_InitStructure;//中斷初始化函數(shù) EXTI_InitTypeDefEXTI_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC,ENABLE);//使能PD,PC端口時鐘 //SoftWareSerialTXD GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//選擇io口6 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽輸出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz GPIO_Init(GPIOD,&GPIO_InitStructure); GPIO_SetBits(GPIOD,GPIO_Pin_6);//TXD默認電平拉高 //SoftWareSerialRXD GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOD,&GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource7);//對D7的下降沿進行中斷采樣,當(dāng)接收到下降沿時代表接收到數(shù)據(jù)觸發(fā)中斷處理函數(shù) EXTI_InitStruct.EXTI_Line=EXTI_Line7;//用到了中斷7 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=EXTI9_5_IRQn;//中斷發(fā)生于9-5的中斷之中 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); }
7、定時器初始化
voidTIM5_Int_Init(u16arr,u16psc) { TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; NVIC_InitTypeDefNVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//時鐘使能 //定時器TIM5初始化 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向上計數(shù)模式 TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);//根據(jù)指定的參數(shù)初始化TIMx的時間基數(shù)單位 TIM_ClearITPendingBit(TIM5,TIM_FLAG_Update); TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);//使能指定的TIM5中斷,允許更新中斷 //中斷優(yōu)先級NVIC設(shè)置 NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;//TIM5中斷 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寄存器 }
對TIM5進行初始化操作使得定時器可以檢測到各個位的電平持續(xù)性時間從而對接收到的數(shù)據(jù)進行分析。計時結(jié)束后進入中斷TIM5處理。
8、外部中斷處理函數(shù)
voidEXTI9_5_IRQHandler(void) { if(EXTI_GetFlagStatus(EXTI_Line7)!=RESET)//對中斷標志位進行采集 { if(OI2_RXD==0) { if(recvStat2==COM_STOP_BIT) { recvStat2=COM_START_BIT;//將當(dāng)前的狀態(tài)設(shè)置為開始位 TIM_Cmd(TIM5,ENABLE);//開啟定時器計數(shù) } } EXTI_ClearITPendingBit(EXTI_Line7);//清除中斷標志 } }
9、定時器中斷處理函數(shù)
voidTIM5_IRQHandler(void) { if(TIM_GetFlagStatus(TIM5,TIM_FLAG_Update)!=RESET) { TIM_ClearITPendingBit(TIM5,TIM_FLAG_Update);//清除中斷標志位 recvStat2++;//將位置移動到第一位的數(shù)據(jù) if(recvStat2==COM_STOP_BIT)//當(dāng)運行到停止位時進入 { TIM_Cmd(TIM5,DISABLE);//停止tim5 USART2_buf[len2++]=recvData2;//將采集到的各個數(shù)據(jù)傳遞給USART2_buf if(len2>Recive2_Byte-1)//將數(shù)據(jù)通過回顯到串口調(diào)試助手中 { len2=0; USART2_Send(USART2_buf,Recive2_Byte); } return; } if(OI2_RXD)//采集RXD各個電平 { recvData2|=(1<(recvStat2?-?1)); ????????}else{ ????????????recvData2?&=?~(1?<(recvStat2?-?1)); ????????}? ??}?? }
整體代碼
vuart2.c
#include"stm32f10x.h" #include"vuart2.h" /** *軟件串口的實現(xiàn)(IO模擬串口) *波特率:9600 1-8-N *TXD:PD6 *RXD:PD7 *使用外部中斷對RXD的下降沿進行觸發(fā),使用定時器5按照9600波特率進行定時數(shù)據(jù)接收。 *Demo功能:接收11個數(shù)據(jù),然后把接收到的數(shù)據(jù)發(fā)送出去 */ #defineOI2_TXDPDout(6) #defineOI2_RXDPDin(7) #defineBuadRate2_9600104 #defineRecive2_Byte19//接收緩沖器的個數(shù) u8len2=0;//接收計數(shù) u8USART2_buf[Recive2_Byte];//接收緩沖區(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, }; u8recvStat2=COM_STOP_BIT; u8recvData2=0; voidIO2_TXD(u8Data) { u8i=0; OI2_TXD=0; delay_us(BuadRate2_9600); for(i=0;i8;?i++) ????{ ????????if(Data&0x01) ????????????OI2_TXD?=?1;?? ????????else ????????????OI2_TXD?=?0;?? ???????? ????????delay_us(BuadRate2_9600); ????????Data?=?Data>>1; } OI2_TXD=1; delay_us(BuadRate2_9600); } voidUSART2_Send(u8*buf,u8len2) { u8t; for(t=0;tRecive2_Byte-1) { len2=0; USART2_Send(USART2_buf,Recive2_Byte); } return; } if(OI2_RXD) { recvData2|=(1<(recvStat2?-?1)); ????????}else{ ????????????recvData2?&=?~(1?<(recvStat2?-?1)); ????????}? ??}?? }
vuart2.h
#ifndef__VUART2__H #define__VUART2__H #include"stm32f10x.h" voidIO2_TXD(u8Data); voidUSART2_Send(u8*buf,u8len); voidIO2Config(void); voidTIM5_Int_Init(u16arr,u16psc); #endif
審核編輯:湯梓紅
-
單片機
+關(guān)注
關(guān)注
6035文章
44554瀏覽量
634614 -
通信
+關(guān)注
關(guān)注
18文章
6024瀏覽量
135949 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355721 -
串口
+關(guān)注
關(guān)注
14文章
1551瀏覽量
76421 -
uart
+關(guān)注
關(guān)注
22文章
1235瀏覽量
101352
原文標題:STM32 模擬串口(UART)使用!
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論