打印
[STM32F1]

怎么实现单线脉宽调制传输

[复制链接]
3287|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wildeer|  楼主 | 2015-6-19 13:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
需要通过STM32F103实现单线归零码(脉宽调制码)传输,比如0的高低电平占空比为1:4, 1的高低电平占空比为4:1, 基准电平宽度0.25us,想通过DMA+某种通讯口实现,可找了很久没有合适方案,请教高人指点。
不要普通IO加延时的方案,因为太占用CPU资源。
沙发
Thor9| | 2015-6-19 17:43 | 只看该作者
帮你顶了

使用特权

评论回复
板凳
wowow| | 2015-6-19 23:45 | 只看该作者
可以用DMA+TIM。TIM_CHx设成PWM输出,用update中断触发DMA更新CCRx值。
将要发送的bit流转成CCRx值的数组,作为DMA的源内存地址,CCRx寄存器设成DMA的目的外设地址。

使用特权

评论回复
地板
戈卫东| | 2015-6-20 07:47 | 只看该作者
你这是不归零调制

使用特权

评论回复
5
wildeer|  楼主 | 2015-6-20 09:04 | 只看该作者
wowow 发表于 2015-6-19 23:45
可以用DMA+TIM。TIM_CHx设成PWM输出,用update中断触发DMA更新CCRx值。
将要发送的bit流转成CCRx值的数组, ...

这是一个思路,我如下理解不知是否正确:设置PWM周期为基准电平宽度0.25us,周期内不翻转(只有一种电平),这样码流数据量将扩大5倍,0将变成10000,1成为11110,这也需要CPU来完成,RAM占用也要扩大5倍,虽然可以实现,工作量却不少,有没有更好的方案呢?

使用特权

评论回复
6
wildeer|  楼主 | 2015-6-20 09:06 | 只看该作者
戈卫东 发表于 2015-6-20 07:47
你这是不归零调制

归零码码元中间的信号回归到0电平,而非归零码遇1电平翻转,零时不变。

使用特权

评论回复
7
icecut| | 2015-6-20 11:33 | 只看该作者
本帖最后由 icecut 于 2015-6-20 11:36 编辑
wildeer 发表于 2015-6-20 09:04
这是一个思路,我如下理解不知是否正确:设置PWM周期为基准电平宽度0.25us,周期内不翻转(只有一种电平 ...

你理解不正确.你那说法是 dma 直接给 gpio,当然 dma 不支持1bit 的 gpio 串行发数.最低一个字节发一次.所以放大比要更大.大约1:40

设置周期为5
发1给定时器是1:4,
发4给定时器是4:1
放大比为1:8

使用特权

评论回复
8
wildeer|  楼主 | 2015-6-20 14:00 | 只看该作者
icecut 发表于 2015-6-20 11:33
你理解不正确.你那说法是 dma 直接给 gpio,当然 dma 不支持1bit 的 gpio 串行发数.最低一个字节发一次.所 ...

我的意思是通过定时器PWM管脚输出。DMA可以直接从GPIO输出吗?看DMA映射表,好像没有哦。
刚才理解有点问题,如果这样,放大比将是80倍(定时器是16位),太恐怖了
应该是将每bit转换为PWM比较基数,对16位定时器,放大比为16倍。此时0转为65535/5 = 13107,1转为65535*4/5 = 52428,这样理论上应该是可以的,数据量稍大点,就太吃内存了。
有没有更好的办法?是否可能通过I2C来实现?只用SDA,可协议比较麻烦,我不太了解I2C,哪位大侠知道的帮我分析一下。

使用特权

评论回复
9
wildeer|  楼主 | 2015-6-20 14:00 | 只看该作者
icecut 发表于 2015-6-20 11:33
你理解不正确.你那说法是 dma 直接给 gpio,当然 dma 不支持1bit 的 gpio 串行发数.最低一个字节发一次.所 ...

我的意思是通过定时器PWM管脚输出。DMA可以直接从GPIO输出吗?看DMA映射表,好像没有哦。
刚才理解有点问题,如果这样,放大比将是80倍(定时器是16位),太恐怖了
应该是将每bit转换为PWM比较基数,对16位定时器,放大比为16倍。此时0转为65535/5 = 13107,1转为65535*4/5 = 52428,这样理论上应该是可以的,数据量稍大点,就太吃内存了。
有没有更好的办法?是否可能通过I2C来实现?只用SDA,可协议比较麻烦,我不太了解I2C,哪位大侠知道的帮我分析一下。

使用特权

评论回复
10
icecut| | 2015-6-20 20:09 | 只看该作者
还是用硬件实现吧.cpld 之类.
1bit,要转2byte给 pwm
1byte = 16byte,
你一次转16字节,供256byte,内存还能扛得住吧.dma 16字节中断一次继续下一个转换.

你理解还是不对.没有80倍.pwm 接收的是一个比例,一个数完成一个波

使用特权

评论回复
11
wowow| | 2015-6-21 08:48 | 只看该作者
本帖最后由 wowow 于 2015-6-21 08:50 编辑

数据流较长时用用循环缓冲区,发送一半和全部发送完都触发一次DMA中断,处理下一批要发送的bit流
比如有1k bit要发,一次发32bit,定义一个64x16bit的数组做缓冲区,先一将64bit转成64个CCR值存到数组里,启动动DMA
发送一半的中断里再转新的32bit填到缓冲区前半段,此时DMA正在发后半段。
发送完成中断,再转新的32bit填到缓冲区后半段,此时由于是设成循环模式,DMA自动转到缓冲区开头发送。
如此循环直到全部发完。
如果你的数据也是持续的数据流,也是这样的方法,跟你的数据流配合好就行了。
内存不够的话一次发8bit也行,就是中断频繁些而已。

使用特权

评论回复
12
小小刀| | 2015-6-23 15:53 | 只看该作者
同意楼上的看法,可以参考Project\STM32F10x_StdPeriph_Examples\TIM\DMA中的例子,DMA传值到CCR,改变占空比

使用特权

评论回复
13
yiyigirl2014| | 2015-6-23 20:30 | 只看该作者
你这是不归零调制吗

使用特权

评论回复
14
734774645| | 2015-6-23 21:03 | 只看该作者
同意楼上的看法,可以参考Project\STM32F10x_StdPeriph_Examples\TIM\DMA中的例子,DMA传值到CCR,改变占空比

使用特权

评论回复
15
hudi008| | 2015-6-23 22:07 | 只看该作者
串口信号。

使用特权

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

本版积分规则

3

主题

13

帖子

0

粉丝