#include "includes.h" /********************************************* 使用说明: 1.首先把TIM_TX_Configuration(),TIM_RX_Configuration(),EXTIinit()中NVIC相关的配置配置好 2.添加中断函数TIM2_IRQHandler(),TIM3_IRQHandler(),EXTI15_10_IRQHandler() 3.根据当前主频和所需的波特率,配置执行VirtualCOM_Init(SYSCLK_FREQ_36M,BAUDRATE_9600)初始化函数, 然后就可以从定时器中断中获取接收到的数据,以及使用VirtualCOM_StringSend("abc\r\n")发送数据 备注:此方案用了3个定时器,其中TIM2的作为仅是做延迟,完全可以用COM_RX_Start_Delay(n)取合适的值代替,省一个定时器 ***********************************************/ unsigned char g_ucRecvStat = COM_STOP_BIT; unsigned char g_ucRecvData = 0; unsigned char g_iDelayCt=26;//当定时器配置最小时间为5us时,g_iDelayCt固定取26 int iPrescaler =0; int iPeriod = 0; unsigned char iPeriodFix = 14; int g_iCOMRXDelayCt = 0; /************************************ TIM_Delay_us *************************************/ int g_iTIM_DelayUs_ct=0; void TIM_Delay_us(int timeus)// { g_iTIM_DelayUs_ct = timeus; TIM_Cmd(TIM2,ENABLE); while(g_iTIM_DelayUs_ct>0); TIM_Cmd(TIM2,DISABLE); } /************************************ 配置定时器中断参数 *************************************/ void TIM_TX_Configuration() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // NVIC_InitTypeDef NVIC_InitStructure;//定时器中断向量配置已放在MY_NVIC_Init()中 // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_DeInit(TIM2); TIM_InternalClockConfig(TIM2); TIM_TimeBaseStructure.TIM_Prescaler = iPrescaler - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = iPeriod - 1; TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); TIM_Cmd(TIM2,DISABLE); // NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); } void TIM_RX_Configuration() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // NVIC_InitTypeDef NVIC_InitStructure;//定时器中断向量配置已放在MY_NVIC_Init()中 // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_DeInit(TIM3); TIM_InternalClockConfig(TIM3); TIM_TimeBaseStructure.TIM_Prescaler = iPrescaler - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = iPeriod*g_iDelayCt + iPeriodFix; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); TIM_ClearFlag(TIM3, TIM_FLAG_Update); TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); TIM_Cmd(TIM3,DISABLE); // NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); } void TIM_IDLE_TD_Configuration()//空闲保存数据定时器中断 { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // NVIC_InitTypeDef NVIC_InitStructure;//定时器中断向量配置已放在MY_NVIC_Init()中 // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_DeInit(TIM4); TIM_InternalClockConfig(TIM4); TIM_TimeBaseStructure.TIM_Prescaler = iPrescaler - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = iPeriod*g_iDelayCt*10 - 1; TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure); TIM_ClearFlag(TIM4, TIM_FLAG_Update); TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); TIM_Cmd(TIM4,DISABLE); // NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); } /************************************ 配置外部中断 *************************************/ void EXTIinit(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; // NVIC_InitTypeDef NVIC_InitStructure;//外部中断向量配置已放在MY_NVIC_Init()中 // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE); GPIO_InitStructure.GPIO_Pin = COM_RX_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(COM_RX_PORT, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource13); EXTI_InitStructure.EXTI_Line = EXTI_Line13; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //外部中断 // NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; // NVIC_Init(&NVIC_InitStructure); } /************************************ 配置串口IO *************************************/ void VirtualCOM_IOconfig() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); GPIO_InitStructure.GPIO_Pin = (COM_TX_PIN); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(COM_TX_PORT, &GPIO_InitStructure); GPIO_SetBits(COM_TX_PORT, COM_TX_PIN); // GPIO_InitStructure.GPIO_Pin = (COM_RX_PIN); //在EXTIinit()中配置 // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // GPIO_Init(COM_RX_PORT, &GPIO_InitStructure); } /************************************ 初始化模拟串口 *************************************/ void VirtualCOM_Init(SYSCLK_FREQ SysclkFreq,BAUDRATE BaudRate) { switch (SysclkFreq) { case (SYSCLK_FREQ_72M): if(BaudRate == BAUDRATE_9600) {iPrescaler=24;iPeriod=12;g_iCOMRXDelayCt=150;} if(BaudRate == BAUDRATE_4800) {iPrescaler=48;iPeriod=12;g_iCOMRXDelayCt=300;} if(BaudRate == BAUDRATE_2400) {iPrescaler=96;iPeriod=12;g_iCOMRXDelayCt=600;} if(BaudRate == BAUDRATE_1200) {iPrescaler=192;iPeriod=12;g_iCOMRXDelayCt=1200;} break; case (SYSCLK_FREQ_48M): if(BaudRate == BAUDRATE_9600) {iPrescaler=16;iPeriod=12;g_iCOMRXDelayCt=110;} if(BaudRate == BAUDRATE_4800) {iPrescaler=32;iPeriod=12;g_iCOMRXDelayCt=220;} if(BaudRate == BAUDRATE_2400) {iPrescaler=64;iPeriod=12;g_iCOMRXDelayCt=440;} if(BaudRate == BAUDRATE_1200) {iPrescaler=128;iPeriod=12;g_iCOMRXDelayCt=880;} break; case (SYSCLK_FREQ_36M): if(BaudRate == BAUDRATE_9600) {iPrescaler=12;iPeriod=12;g_iCOMRXDelayCt=80;} if(BaudRate == BAUDRATE_4800) {iPrescaler=24;iPeriod=12;g_iCOMRXDelayCt=160;} if(BaudRate == BAUDRATE_2400) {iPrescaler=48;iPeriod=12;g_iCOMRXDelayCt=320;} if(BaudRate == BAUDRATE_1200) {iPrescaler=96;iPeriod=12;g_iCOMRXDelayCt=640;} break; } VirtualCOM_IOconfig(); TIM_TX_Configuration(); TIM_RX_Configuration(); TIM_IDLE_TD_Configuration(); EXTIinit(); } /************************************ VirtualCOM_ByteSend 发送一个字节 *************************************/ void VirtualCOM_ByteSend(unsigned char val) { u8 i = 0; COM_DATA_LOW(); TIM_Delay_us(g_iDelayCt); for(i = 0; i < 8; i++) { if(val & 0x01) COM_DATA_HIGH(); else COM_DATA_LOW(); TIM_Delay_us(g_iDelayCt); val >>= 1; } COM_DATA_HIGH(); TIM_Delay_us(g_iDelayCt); } /************************************ VirtualCOM_StringSend 发送字符串 *************************************/ void VirtualCOM_StringSend(u8 *str) { while(*str != 0) { VirtualCOM_ByteSend(*str); str++; } } /************************************ COM_RX_Start_Delay 接收启动定时器延迟函数 *************************************/ void COM_RX_Start_Delay(int ct) { while(ct-->0){ __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop(); } } /************************************************** 以下是中断代码 *************************************************** unsigned char g_ucRX_START=0; unsigned char g_ucRX_STOP=0; char RecvBuf[1024]; int RecvBufCt=0; void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){ g_iTIM_DelayUs_ct--; if(g_iTIM_DelayUs_ct<=0)TIM_Cmd(TIM2,DISABLE); TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); } } void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){ g_ucRecvStat++; if(g_ucRecvStat == COM_STOP_BIT){ TIM_Cmd(TIM3, DISABLE); TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update); RecvBuf[RecvBufCt]=g_ucRecvData; RecvBufCt++; g_ucRX_STOP=1; TIM_Cmd(TIM4,ENABLE); return; } if(COM_RX_STAT){ //'1' g_ucRecvData |= (1 << (g_ucRecvStat - 1)); } else{ //'0' g_ucRecvData &= ~(1 <<(g_ucRecvStat - 1)); } TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update); } } void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET){ if(g_ucRX_START==1 && g_ucRX_STOP==1){ g_ucRX_START=0; g_ucRX_STOP=0; // printf("%s\r\n",RecvBuf);//此处RecvBuf已接收完整,可以取出 RecvBufCt=0; memset(RecvBuf,0,sizeof(RecvBuf)); TIM_Cmd(TIM4,DISABLE); } TIM_ClearITPendingBit(TIM4,TIM_FLAG_Update); } } void EXTI15_10_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line13)!=RESET) { if(!COM_RX_STAT) { if(g_ucRecvStat == COM_STOP_BIT) { g_ucRecvStat = COM_START_BIT; COM_RX_Start_Delay(g_iCOMRXDelayCt); TIM_Cmd(TIM3, ENABLE); g_ucRX_START=1; g_ucRX_STOP=0; TIM_Cmd(TIM4,DISABLE); } } EXTI_ClearITPendingBit(EXTI_Line13); } } *************************************************** end ***************************************************/