打印

stm32 IO模拟串口代码

[复制链接]
909|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
王大熊|  楼主 | 2015-11-24 23:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
发送数据:

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               
                }       
        }
//        while(i--)
//        {  
//          MNUSART_TXD = (Byte&0x01);     //先传低位
//          delay_us(104);          
//          Byte = Byte>>1;
//          //无校验位
//          MNUSART_TXD=1;//发送结束位
//          delay_us(104);
       
//        }
         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++);

}

接收用的外部中断:

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 端口配置
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
   GPIO_Init(GPIOA, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOB.5
   GPIO_SetBits(GPIOA,GPIO_Pin_9);                                                 
       
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
   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--)
          {
                  tmp >>=1;
                if(GPIOA->IDR&0x0400) tmp |=0x80;
                delay_us(104);
       
          }
          if((USART_RX_STA&0x8000)==0)
          {
                   if(USART_RX_STA&0x4000)
                 {
                  if(tmp!=0x0a) USART_RX_STA=0;
                  else USART_RX_STA |=0x8000;
                 }
                 else
                 {
                   if(tmp==0x0d) USART_RX_STA|=0x4000;
                   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);

   }

}

主函数:

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);
//测试发送字符串
// SendBytes("hello word",11);
// SendStr("德玛西亚");       

  while(1)
        {
          if(USART_RX_STA&0x8000)
          {          
             printf("\r\n您发送的消息为:\r\n\r\n");
                   len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
                 SendBytes(USART_RX_BUF,len);
                 //也可以用下面的发送
//                 SendStr(USART_RX_BUF);
//                 for(len=0;len<200;len++)
//                 USART_RX_BUF[len]=0;
                   printf("\r\n\r\n");//插入换行
                USART_RX_STA=0;
          }
        }
}

相关帖子

沙发
deliciouscook| | 2015-11-24 23:01 | 只看该作者
你的模拟串口,接受部分代码写的不好,没有采样,,直接延迟。。。建议采样频率为波特率的3-5倍。

使用特权

评论回复
板凳
justperky| | 2015-11-24 23:01 | 只看该作者
NVIC->ICER[EXTI15_10_IRQn >> 0x05] =
               (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
楼主这个什么意思哈

使用特权

评论回复
地板
王大熊|  楼主 | 2015-11-24 23:02 | 只看该作者
justperky 发表于 2015-11-24 23:01
NVIC->ICER[EXTI15_10_IRQn >> 0x05] =
               (uint32_t)0x01

PA10上的下降沿将触发外部中断,这标志着“起始位0”的到来。在对应的中断服务程序中,会立即关闭该外部中断 NVIC->ICER[EXTI15_10_IRQn >> 0x05] =
               (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);,以防后续的“数据位”误触发本中断。接收完毕之后,打开外部中断NVIC->ISER[EXTI15_10_IRQn >> 0x05] =
            (uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);

使用特权

评论回复
5
蜕变吧| | 2015-11-24 23:02 | 只看该作者
deliciouscook 发表于 2015-11-24 23:01
你的模拟串口,接受部分代码写的不好,没有采样,,直接延迟。。。建议采样频率为波特率的3-5倍。 ...

串口没有采样之说,不是频率信号。假设如果把串口波特率放慢到1秒一位,一个字节的数据按照1位起始,8位数据,1位停止,共需要10秒。
每个位(包括起始、停止)的数值是高或者低,都需要在这个位对应的秒时读取。

例如第3位为高电平,从第4秒到第5秒这一秒的时间中,任何时刻读取数值都可以。
但是只能读取一次,及时读取多次,也不能把后续读取的数值作为第4位,只有当第5秒和第6秒到来时,才能读取第4位。

楼主写的程序,我持赞成态度。
使用起始位的从低到高电平跳转上升沿,触发外部中断。
然后关闭外部中断,防止8位数据中出现的电平跳转再次触发中断。打乱下面的while部分。
再然后清除中断标志,使delay_us可以起作用,因为这个delay用的是系统滴答中断。
然后延迟30uS,此时取电平正好是第一位数据,取到第8次,数据取完,取第9次,取出停止位。

再然后就没什么好说的了。

我感觉最后两段话,开中断可以有,清中断标志就不必了

使用特权

评论回复
6
STM32初学者| | 2015-11-26 22:28 | 只看该作者
我决定楼主的代码写的不错,不过串口模拟,现在基本不会用到了。基本上很多芯片都带串口资源的。

使用特权

评论回复
7
zhangyi3312| | 2015-11-28 14:53 | 只看该作者
蜕变吧 发表于 2015-11-24 23:02
串口没有采样之说,不是频率信号。假设如果把串口波特率放慢到1秒一位,一个字节的数据按照1位起始,8位 ...

居然有这么多的讲究,我要仔细看看这个代码了。

使用特权

评论回复
8
liiwang| | 2015-12-12 11:35 | 只看该作者
楼主,你好,我想问一下,你那个接收程序在中断里面为什么是延迟30uS,起始为不是有104uS么?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

236

帖子

0

粉丝