香版主请进-请问怎样出高精度的波形(误差在0.1uS之内)

[复制链接]
 楼主| gz_ddc 发表于 2012-4-13 15:27 | 显示全部楼层 |阅读模式
遇到麻烦,请大力帮帮忙。谢谢。

一个103RBT6,72M FCLK. 我需要先出1uS的高电平,然后出0.5uS的低电平。或反过来,误差不能超过100nS.
(也就是0.5uS的电平,误差也不能超过100nS)。怎样才能最精确呢?我用普通单片机汇编可以很轻易出这样的波形,但是这里搞不定。其实100nS之内, FCLK 72M 的STM32应该都能执行很多条指令了吧?怎么延时不准的呢?

我用下面的代码不行。我这里没有数字存储示波器,不能抓波形来看。只能用软件仿真的方式观察波形,而软件仿真看到的波形的读数去不到纳秒级。我观察0码的长度比例为(我用尺子量) 1:1.7    而1码的长度比例为  1.5:1.178  。偏差太大了吧? 问题出在哪里呢?该怎样改呢? (但不排除软件仿真的显示结果有问题)

void send_dat(void)
{
  u8 i,j,t;
  RCC->APB1ENR|=1<<1;   //TIM3时钟使能
  TIM3->PSC=0;
  TIM3->DIER|=1<<0;
  TIM3->CR1|=1<<3;      //单脉冲模式
  for (i=0;i<buff_size;i++)
  {
    t=buf[i];
    for (j=0;j<8;j++)
    {
      if (t&0x80)
      {
        DAT0=1;
        TIM3->ARR=72;         //1uS的定时器
        TIM3->CR1|=1<<0;
        while (!(TIM3->SR&1)) ;
        TIM3->SR&=~1;
        DAT0=0;
        TIM3->ARR=36;         //0.5uS的定时器
        TIM3->CR1|=1<<0;
        while (!(TIM3->SR&1)) ;
        TIM3->SR&=~1;
      }
      else
      {
        DAT0=1;
        TIM3->ARR=36;         //0.5uS的定时器
        TIM3->CR1|=1<<0;
        while (!(TIM3->SR&1)) ;
        TIM3->SR&=~1;
        DAT0=0;
        TIM3->ARR=72;         //1uS的定时器
        TIM3->CR1|=1<<0;
        while (!(TIM3->SR&1)) ;
        TIM3->SR&=~1;
      }   
      t<<=1;
    }  
  }
}
香水城 发表于 2012-4-13 15:39 | 显示全部楼层
你的方向错了,不应该用程序翻转端口,应该直接用定时器的输出。
 楼主| gz_ddc 发表于 2012-4-13 15:45 | 显示全部楼层
怎样直接用定时器输出啊?你指用pwm的方式吗?我也在试这个。不过还没写出来。是不是还有更简单的方法?能不能像我原先的代码差不多,还是用定时器单步方式?

可不可以写些代码给我?有些急。
谢谢。
airwill 发表于 2012-4-13 16:00 | 显示全部楼层
用 pwm 的方式,  可行.
用定时器单步方式, 调整不便, 不合适.

是不是还有更简单的方法?这已经够简单了, 要想高精度, 没有了. 只有复杂的.
像我原先的代码差不多?  由于 CPU 流水线方面的问题, 没有办法提高精度.
 楼主| gz_ddc 发表于 2012-4-13 16:12 | 显示全部楼层
我需要具体的代码指导。可以给代码我吗?
谢谢。
香水城 发表于 2012-4-13 16:58 | 显示全部楼层
没有鱼,只有加了水的渔,:)
 楼主| gz_ddc 发表于 2012-4-13 17:20 | 显示全部楼层
搞不定啊,pwm出一般波形我知道,但是我这个送完一个周期的信号后,怎么送接下来那个周期的?(我怎么判断第一个周期结束了?是判断TIM3->SR&1 吗?怎么我试了好像不行。)
mxh0506 发表于 2012-4-13 20:11 | 显示全部楼层
不是1us高+0.5us低吗? 下一个周期难道不是这样的?
 楼主| gz_ddc 发表于 2012-4-13 20:41 | 显示全部楼层
不是,见我最上面的程序,根据相关情况,下一个周期可能是先0.5u高,再1u低。

8# mxh0506
jiayou0054 发表于 2012-4-13 22:00 | 显示全部楼层
想精度高,应该提高时钟频率呢。
IJK 发表于 2012-4-13 22:03 | 显示全部楼层
可以用SPI来模拟,很容易,其实才相当于2MHz的波特率。当然,有一个困难之处就是,SPI 发出的数必须连续,不能断
airwill 发表于 2012-4-13 22:38 | 显示全部楼层
楼上倒也是一个办法, 如果应付简单出几个波形, 特别有效.
楼主的 PWM 更改, 可以采用溢出更新方式, 这样可以提前将下一次的周期和占空比预先设置好
王紫豪 发表于 2012-4-13 22:52 | 显示全部楼层
这东西,用 cpld 比较合适。。。
触觉的爱 发表于 2012-4-14 01:23 | 显示全部楼层
汽车的灵活性远不如摩托:lol
nongfuxu 发表于 2012-4-14 04:33 | 显示全部楼层
我需要先出1uS的高电平,然后出0.5uS的低电平。或反过来,误差不能超过100nS.

应该直接用定时器的输出

100ns精度,我看行.
joyme 发表于 2012-4-14 11:08 | 显示全部楼层
PWM输出只要设置好周期和占空比就好了吧
rockli 发表于 2012-4-14 14:38 | 显示全部楼层
对高速时序要求严格,还是cpld吧
seawwh 发表于 2012-4-14 20:13 | 显示全部楼层
建议采用 TIM 定时输出,触发条件使用DMA方式提供,这样输出波形是没有误差的。
可以先将数据翻译为N*8个控制字,放置在RAM中,然后启动DMA即可。
当然,如果RAM空间有限的话,可以边翻译边输出的办法。
 楼主| gz_ddc 发表于 2012-4-18 15:04 | 显示全部楼层
香版主, airwill,seawwh:
我改成下面的方式,基本上可以,但是好像临停止的时候(脉冲流的尾段)会送多一个到两个错误的脉冲。
请帮忙看看是什么问题。
代码是这样的:
    ......
    ......
    if (buff[t]&0x08) TIM4->CCR2=50; else TIM4->CCR2=130;   //(A处)
    while (!(TIM4->SR&1)) ;                           
    TIM4->SR&=~1;                            //清除更新事件标志
    if (buff[t]&0x04) TIM4->CCR2=50; else TIM4->CCR2=130;   //(B处)     //这里不等A处设置的pwm时间周期结束,就直接再写入新的参数,利用预装载功能
    while (!(TIM4->SR&1)) ;                  //检查更新事件。这里等待的是A处设置的pwm时间周期结束
    TIM4->SR&=~1;
    if (buff[t]&0x02) TIM4->CCR2=50; else TIM4->CCR2=130;   //(C处)
    while (!(TIM4->SR&1)) ;
    TIM4->SR&=~1;
    if (buff[t]&0x01) TIM4->CCR2=50; else TIM4->CCR2=130;   //(D处)
    while (!(TIM4->SR&1)) ;                           //这里等待的是C处设置的pwm时间周期结束
    TIM4->SR&=~1;                                      //D处设置的pwm时间周期这时还没有结束       
  }
  TIM4->CR1|=1<<3;       //到最后了,改单脉冲模式,这个脉冲结束时,定时器自动停止。但最后好像会送多一到两个错误脉冲出去。

seawwh:你说用DMA触发定时器方式,有没有相关例子或资料?谢谢。

大家请帮忙。

谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

12

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部