▼點擊下方名片,關注公眾號,獲取更多精彩內容▼

歡迎關注【玩轉單片機與嵌入式】公眾號,回復關鍵字獲取更多免費視頻和資料
回復【加群】,【單片機】、【STM32】、【硬件知識】、【硬件設計】、【經典電路】、【論文】、【畢業設計】、【3D封裝庫】、【PCB】、【電容】、【TVS】、【阻抗匹配】、【資料】、【終端電阻】、【Keil】、【485】、【CAN】、【振蕩器】、[USBCAN]、【PCB】、【智能手環】、【智能家居】、【智能小車】、【555】、【I2C】、【華為】、【中興】,等……

????如果在實際使用中只是為了打印log而不接收數據,可以采用DWT加普通IO口的方式;
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;elsedat[i] = 0;ch >>= 1;}OS_CPU_SR cpu_sr;enter_critical();//以下代碼進行臨界保護,防止被中斷打斷造成發送誤碼dwt_start();VCOM_PIN_LOW; //發送起始位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;elseVCOM_PIN_LOW;time_stamp = BSP_REG_DWT_CYCCNT;while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //發8bit 數據位}VCOM_PIN_HIGH;time_stamp = BSP_REG_DWT_CYCCNT;while(BSP_REG_DWT_CYCCNT < (time_stamp+bit_width)); //發停止位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++;}}
????實現方式: 普通定時器+普通IO口中斷+fifo
/***軟件串口的實現(IO模擬串口)* 波特率:9600 1-8-N* TXD : PC13* RXD : PB14* 使用外部中斷對RXD的下降沿進行觸發,使用定時器4按照9600波特率進行定時數據接收。* Demo功能: 接收11個數據,然后把接收到的數據發送出去*/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;elseOI_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 TXDGPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHzGPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_SetBits(GPIOC,GPIO_Pin_13);//SoftWare Serial RXDGPIO_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_timTIM_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));}}}
聲明||文章轉載自網絡,若有侵權請聯系刪除,謝謝。
1、歡迎關注本公眾號,回復【STM32】可以獲取更多STM32相關的視頻和設計資料。
END


掃描上方二維碼加群,回復【加群】或掃碼加我好友,限時免費進入技術交流群。

感謝大家閱讀,如果喜歡
請點贊和“在看”吧,或者分享到朋友圈。
點擊跳轉到原文,限時優惠加入我們的知識星球(加好友獲取免費券)