STM32外部中断模拟UART串口

/*********************************************************************************************/

串口数据帧发送格式:1个起始位 + 8个数据位 + 1个停止位

思路:1.PA9做普通IO推挽输出,按照发送格式用延时暂时作为该位的传输时间,波特率为9600

           2.PA10做浮空输入,外部共享中断使用(可用其余外部中断),每接收到一个数据就进中断一次,循环接收判断,当接收到\r\n将接收标志置为0x8000(或为1);

********************************************************************************************/

//加入以下代码,支持printf函数,而不需要选择use MicroLIB      
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 

    int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 

    x = x; 

//重定义fputc函数 
int fputc(int ch, FILE *f)
{  
    void SendOneByte(u8 Byte);
    SendOneByte((uint8_t) ch);    
    return ch;
}
#endif 

//发送一个字节数据
void SendOneByte(u8 Byte)
{
    u8 i=8,tmp;
    TXD_low(); //发送起始位
    delay_us(104);
    //发送8位数据
    for(i=0;i<8;i++)
    {
        tmp    = (Byte >> i) & 0x01;  //低位在前

        if(tmp == 0)
        {
            TXD_low();
            delay_us(104);    //0        
        }
        else
        {
            TXD_high();
            delay_us(104);    //1        
        }    
    }
     TXD_high();//发送停止位
     delay_us(104);

}

//发送数组最好用这个,也可发送字符串
void SendBytes(u8 *str,u8 len)    
{
  u16 i;
  for(i=0;i<len;i++)
  {
       SendOneByte(str[i]);
  }

}

void SendStr(u8 *str) //发送字符串,发送数组如果带0x00就中断发送了
{
 while(*str)
 SendOneByte(*str++);

}

int main(void)
 {
  u8 len;
  u8 hello[]={0x5a,0xa5,0x00,0x00,0x01};
  delay_init();
  EXTIX_Init();
  //测试 发送一个字节
  SendOneByte(0x00);
  SendOneByte(0x01);
  SendOneByte(0x02);
  //测试发送数组
 SendBytes(hello,5);

  while(1)
    {

      if(USART_RX_STA&0x8000)
      {      
         printf("\r\n您发送的消息为:\r\n\r\n");
         len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
         SendBytes(USART_RX_BUF,len);
          printf("\r\n\r\n");//插入换行
          USART_RX_STA=0;
      }
    }
 }

/****************************************************************************************/

u8 tmp;                                 //接收的数据(数据中间转换)
u8 USART_RX_BUF[USART_REC_LEN];//接收缓冲区
u16 USART_RX_STA=0;            //接收完成标志
//extern SendOneByte(u8 Byte);

//外部中断初始化
void EXTIX_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   EXTI_InitTypeDef EXTI_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                 //PA.9 端口配置  --  TX发送端
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //IO口速度为50MHz
   GPIO_Init(GPIOA, &GPIO_InitStructure);                     //根据设定参数初始化GPIOA.9
   GPIO_SetBits(GPIOA,GPIO_Pin_9);                         
    
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;             //PA.10 端口配置 --  RX接收端
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         //浮空输入
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 
   GPIO_Init(GPIOA, &GPIO_InitStructure);                      
   GPIO_SetBits(GPIOA,GPIO_Pin_10); 
   
   //GPIOA.10 中断线以及中断初始化配置   下降沿触发
      GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource10);

      EXTI_InitStructure.EXTI_Line=EXTI_Line10;    
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //中断模式
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//浮空输入
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);         //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;    //中断号
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;//抢占优先级
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          //响应优先级
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //中断使能

   NVIC_Init(&NVIC_InitStructure);
}

/*共享中断接收函数*/
void EXTI15_10_IRQHandler(void)
{
   u8 i=9;
   if(EXTI_GetITStatus(EXTI_Line10) != RESET)
   {
     /* Disable the Selected IRQ Channels -------------------------------------*/
     NVIC->ICER[EXTI15_10_IRQn >> 0x05] = (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
      EXTI_ClearITPendingBit(EXTI_Line10);//清除中断标志
      delay_us(30);
      while(i--)//10个数据  1byete起始位+8byte数据位+1byte停止位
      {
          tmp >>=1;                                //移位
        if(GPIOA->IDR&0x0400) tmp |=0x80;//PA10接收到的数据为1
        delay_us(104);
    
      }

      if((USART_RX_STA&0x8000)==0)//接收标志为0
      {
           if(USART_RX_STA&0x4000)
         {
          if(tmp!=0x0a) USART_RX_STA=0;//未接收到\n,标志清0    '\n' == 0x0a
          else USART_RX_STA |=0x8000;  //接收结束,标志置0x8000
         }
         else
         {
           if(tmp==0x0d) USART_RX_STA|=0x4000;//接收到结束标志\r,表示接收可能快结束  '\r' == 0x0d
           else                                           //未接收完成,接收数据缓存到缓冲区
           {
                USART_RX_BUF[USART_RX_STA&0X3FFF]=tmp ;
                USART_RX_STA++;
                if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收      
           }
         }
      
      }

      EXTI_ClearITPendingBit(EXTI_Line10);
      NVIC->ISER[EXTI15_10_IRQn >> 0x05] =
            (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);

   }

}

串口TX测试结果:(上电后发送)

串口RX测试结果:(发送的数据回传)

作者:广东松山电子实验室

+WeChat(linzebinwinner)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aaa1163548340

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值