找回密码
 立即注册
查看: 3602|回复: 12

使用STC8H单脉冲模拟300-900ns协议遇到的...

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-05-03 14:22:29

3

主题

20

回帖

149

积分

注册会员

积分
149
发表于 2022-12-15 09:35:49 | 显示全部楼层 |阅读模式
本帖最后由 flyarm 于 2022-12-15 15:26 编辑

项目需求:使用PWM功能实现,300-900ns的协议控制

硬件实现: MCU--stc8h1k08      

需求分析:
300.png
根据时序要求 需要产生300ns 和 900ns的高脉冲;此类信号(红外遥控协议,WS2812等)一般精确模拟高脉冲即可,低脉冲要求不高;以24M时钟计算,1us就是需要24个脉冲,300ns需要(24*3/10)约7-8个脉冲;900ns需要(24*9/10)约21-22个脉冲;   程序中使用40个脉冲周期;
如果有PWM+DMA效果应该会更好,因为我用的芯片不支持DMA所以只能放弃;

代码,使用pwm的2P作为输出:


void PWMA_OUT_Configuration(void)
{
  //使用PWM2P输出
    P_SW2 |= 0x80;                              //使能XFR访问
  //  PWMA_Priority(0);

    PWMA_CCER1 = 0x00;   
    PWMA_CCMR2 = 0x60;                          //设置2p PWM2 模式2 输出,启用预装载

    PWMA_CCER1  = 0x30;                         //使能2P通道,比较输出高 有效;
        
    PWMA_SR1 = 0;                               //清标志位
    PWMA_CNTR = 0;                              //清计数器
  
    PWMA_ENO = 0x00;
    PWMA_ENO = ENO2P;                     //使能输出                ENO4P|ENO3N||ENO1N

    PWMA_PS = 0x00;                       //高级 PWM 通道输出脚选择位
    PWMA_PS = PWM2_SW_P12_P13;   
  
    PWMA_ARR = 40;
    PWMA_CCR2 = 30;            

    PWMA_BRK = 0x80;                            //使能主输出
    PWMA_CR1 = 0x88;                           //开始计时  单次脉冲
}


void OutPWM_byte(unsigned char Dout)        //先发高位,把每一位转化成一个pwm脉冲输出
{
        unsigned char i;
        bit        Dbit=0;        

        for(i=0;i<8;i++)
        {
                Dbit        =        (Dout>>(7-i))&0x01;                //从高到低获取bit
                if(Dbit)        {PWMA_CCR2 = 18;}       //40-22
                else                        {PWMA_CCR2 = 33;}        //40-7
                PWMA_CR1 |= 0x01;
                NOP1();                                //每个脉冲的总周期逐渐变小,why?
        }
        NOP40();
}



主程序测试调用:
***********前面省略

        PWMA_OUT_Configuration();
        EA = 1;

        while (1)
        {
                OutPWM_byte(0xF7);
                delay_ms(5);
        }


经测试,发现从第MSbit到LSBit,间隔周期逐渐变小,百思不得其解,不知道什么原因;等会补充一个测试图:
tt.png



回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2022-12-15 10:55:37 | 显示全部楼层
WS2812S的标准时序如下:
TH+TL = 1.25us±150ns, RES>50us
T0H = 0.25us±150ns = 0.10us - 0.40us
T0L = 1.00us±150ns = 0.85us - 1.15us
T1H = 1.00us±150ns = 0.85us - 1.15us
T1L = 0.25us±150ns = 0.10us - 0.40us
两个位数据之间的间隔要小于RES的50us.

使用PWM输出控制WS2812并不是好办法,但单脉冲输出不会有问题,先设置好单脉冲的参数,然后启动即可输出一个单脉冲。

控制WS2812最简单的是用IO操作,但会占用MCU时间,一个灯耗时30us,灯数不多的话,时间占比可以接受就可以了。比如擦欧洲哦100个灯要3ms,20ms刷新一次,时间占比15%,仍有85%的时间给别的任务。
建议使用SPI操作,有DMA更好。
  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15626
发表于 2022-12-15 11:01:15 | 显示全部楼层
飞翔:已请到梁工关注您这个贴,你带老兄弟们在这讨论,将程序放上来,好分析
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-05-03 14:22:29

3

主题

20

回帖

149

积分

注册会员

积分
149
发表于 2022-12-15 11:10:38 | 显示全部楼层
理论上肯定是优选spi+dma
因为要在现有的pwm脚上实现 模拟协议;这样硬件上可以通用; 所以现在的方式就成了我的最优选择;

单个脉冲实现没问题;现在就是连续输出的情况下,总觉得和寄存器配置配合不起来;可能是因为执行时间问题,我继续摸索
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-05-03 14:22:29

3

主题

20

回帖

149

积分

注册会员

积分
149
发表于 2022-12-15 11:44:20 | 显示全部楼层
本帖最后由 flyarm 于 2022-12-15 12:03 编辑

问题已解决,因为原发送代码 移位操作造成时间延时不同,所以周期有差异;
改成如下即可:

static void OutPWM_byte(unsigned char Dout)        //先发高位,把每一位转化成一个pwm脉冲输出
{
        unsigned char i;
        unsigned char        Dbit=0;        

        for(i=0;i<8;i++)
        {
                Dbit        =        Dout&0x80;                //从高到低获取bit
                if(Dbit)        {PWMA_CCR2 = 18;}
                else                        {PWMA_CCR2 = 33;}        
                PWMA_CR1 |= 0x01;
                Dout        =        Dout<<1;                                //等待的时间里 每次移位一次
                while(PWMA_CR1 &0x01);
        }
}


稍晚改到2812灯,测试后上工程源码
  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

718

主题

1万

回帖

1万

积分

管理员

积分
15626
发表于 2022-12-15 12:00:42 | 显示全部楼层
感谢分享,都是爱的奉献
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-05-03 14:22:29

3

主题

20

回帖

149

积分

注册会员

积分
149
发表于 2022-12-16 09:28:37 | 显示全部楼层
基于PWM单脉冲的ws2812实现源程序

PWM_WS2812.zip

131.38 KB, 下载次数: 198

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2022-12-16 11:06:28 | 显示全部楼层
用PWM输出,并且用while等待,不如直接用IO输出,反正都是在那里里等待。
//@24MHz
sbit        DIN = P0^0;    //任意IO, 注意要在程序开始初始化IO为推挽输出
void        Send_1us(void)
{
        NOP(16);        // 6+16T  @24MHz,  实际14~40MHz均可驱动
}

void        Send_color(u8 color)        //发送一个字节颜色值
{
        u8        i;
        i = 8;
        do
        {
                EA = 0;        //发送时禁止中断
                if((color & 0x80) != 0)   //数据1
                {
                        DIN = 1;
                        Send_1us();
                        DIN = 0;   //1T
                        EA = 1;        //1T 发送完一个位数据后允许中断, 但任何中断处理时间要小于RES的50us.
                        NOP(4);        //4T @24MHz
                }
                else
                {
                        DIN = 1;
                        NOP(5);                        // 6T @24MHz, 14~44MHz均可驱动
                        DIN = 0;
                        EA = 1;        //发送完一个位数据后允许中断, 但任何中断处理时间要小于RES的50us.
                        Send_1us();
                }
                color <<= 1;
        }
        while(--i != 0);
}

void        Send_GRB(u8 g, u8 r, u8 b)
{
        Send_color(g);
        Send_color(r);
        Send_color(b);
}
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-05-03 14:22:29

3

主题

20

回帖

149

积分

注册会员

积分
149
发表于 2022-12-16 14:08:16 | 显示全部楼层
本帖最后由 flyarm 于 2022-12-16 14:14 编辑

有道理  单任务用io更好;可是我的应用还有各种任务 中断要考虑,还是用pwm 方便

有支持dma的PWM就更方便了,根本就不需要单脉冲;直接 DMA控制占空比发PWM就好了

0

主题

5

回帖

22

积分

新手上路

积分
22
发表于 2023-4-17 13:16:11 | 显示全部楼层
fly*** 发表于 2022-12-15 11:44
问题已解决,因为原发送代码 移位操作造成时间延时不同,所以周期有差异;
改成如下即可:

while(PWMA_CR1&0X01)?为什么这样写?这样,意思是一个周期输出后,这个寄存器的值会自动的改变吗?我看手册 里面PWMA_CR1=0X01,这样是打开计数器,按照你这样写,难道计数器值等于预设值:PWMA_CCR2之后,这个计数器会自动关闭吗?
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 15:39 , Processed in 0.168574 second(s), 106 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表