完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
您好,我正在尝试改变一个WS212B LED的RA0状态。但是,在使条件语句更快地循环时遇到了问题。我使用的是XC8编译器。我的芯片是PIC16F1615Led数据输出是RA0。这是当前代码,对不起重复数组写入,把它们放入一个循环中,使它们运行得更慢。我想知道如何做到这一点。这里最大的问题是当访问条件if语句时发生的延迟。一些人为此使用SPI,但我已经使用I2C作为附加用途。我附上了一个屏幕截图,显示了m的峰值之间的长延迟。谢谢!
以上来自于百度翻译 以下为原文 Hello, I am trying to change the state of RA0 at a fast speed for an WS2812b led. However I am having problems getting the conditional statements to cycle through faster. I am using XC8 Compiler My chip is PIC16F1615 Led Data output is RA0 Here is the current code #include #include #include "ws2812.h" #include "mcc_generated_files/mcc.h" // the pin that the LEDs are on. I don't like this being in here // but timing is so tight, it is hard to put it elsewhere #define PIN PORTAbits.RA0 unsigned long int bitflip(unsigned char b); unsigned char array[24]; // transmit the ws2812 led void ws2812_send(ws2812_ptr* led) { INTERRUPT_GlobalInterruptDisable(); INTERRUPT_PeripheralInterruptDisable(); int j; long int val; val = (bitflip(led->b) << 16) + (bitflip(led->r) << 8) + (bitflip(led->g)); int k = 0; for(k =0; k<24;k++){ array[k] = val & 1; val = val >> (unsigned char)1; } // the WS2812 wants bits in the order of: // GGGGGGGGRRRRRRRRBBBBBBBB // but I want to work in the opposite order. so i'm going to flip // the bits around and do some shifting so my order is // BBBBBBBBRRRRRRRRGGGGGGGG // with the most significant bit on the far right. so the RGB value // of 128 64 32, which normally would be: // R : 0b10000000 // G : 0b01000000 // B : 0b00100000 // will become: // BBBBBBBBRRRRRRRRGGGGGGGG // 000001000000000100000010 // now begin shifting them over one at a time if (array[0]) { // if it is a 1, let it stay higher a bit longer //asm("BSF LATA, 0"); IO_RA0_LAT = 1; //asm("NOP n NOP"); NOP(); //asm("BCF LATA, 0"); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible //asm("BSF LATA, 0"); //asm("NOPn NOP"); //asm("BCF LATA, 0"); IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[1]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[2]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[3]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[4]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[5]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[6]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[7]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[8]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[9]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[10]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[11]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[12]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[13]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[14]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[15]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[16]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[17]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[18]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[19]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[20]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[21]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[22]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } if (array[23]) { // if it is a 1, let it stay higher a bit longer IO_RA0_LAT = 1; NOP(); IO_RA0_LAT = 0; } else { // but a 0 should go high and then low as fast as possible IO_RA0_LAT = 1; IO_RA0_LAT = 0; } INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); } // reverse the bits in a char unsigned long int bitflip(unsigned char b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return (unsigned long int)b; } Sorry about the repetitive array writing putting them into a loop make it run slower. I was wondering how I can do this with in-line assembly because that seems to run faster The big issue here is the delay that occurs when the conditional if statements are accessed. Some people use SPI for this but I am already using I2C for additional purpose. I have attached a screenshot that show the long delay between the peaks of my signal Thanks in advance! Attached Image(s) |
|
相关推荐
11个回答
|
|
由于您的设备具有CLC,因此通过查找描述如何使用CLC驱动WS2812B的App Note,您可能会得到更好的服务。
以上来自于百度翻译 以下为原文 Since your device has a CLC you'd probably be better served by looking up the App Note that describes how to use the CLC to drive WS2812B's. |
|
|
|
整个“BITFLIP())代码看起来非常繁琐。为什么不在填充数组的时候这么做呢?例如,替换,你定义一个名为“PIN”的值为“Purabutial.Ra0”,BIT然后从不使用它。我猜你意识到你应该使用LababIT.LATA0来代替。
以上来自于百度翻译 以下为原文 The whole "bitflip() bit of code looks very cumbersome. Why not do it as you are filling your array? e.g. replace: long int val; val = (bitflip(led->b) << 16) + (bitflip(led->r) << 8) + (bitflip(led->g)); int k = 0; for(k =0; k<24;k++){ array[k] = val & 1; val = val >> (unsigned char)1; } with unsigned char val; int k; val = led->g; for(k=0; k<7; k++){ array[k] = 0; if (val & 0x80) array[k] = 1; val <<= 1; } val = led->r; for(; k<15; k++){ array[k] = 0; if (val & 0x80) array[k] = 1; val <<= 1; } val = led->b; for( k<23; k++){ array[k] = 0; if (val & 0x80) array[k] = 1; val <<= 1; } Note, you define a value called "PIN" to be "PORTAbits.RA0", bit then never use it. I guess you realised you should be using LATAbits.LATA0 instead. |
|
|
|
不要将数组移动到本地并移动它。我有一个32MHz的PIC16F1937,带有WS2812和WS2812Bseehttps://cpldcpu.com/2014/01/14/light_ws2812-library-v2-0-part-i-.-the-ws2812/for实际的芯片计时。
以上来自于百度翻译 以下为原文 Don't shift the array move the byte to a local and shift it. I have it working on a PIC16F1937 at 32 MHz with the Free XC8 with a WS2812 and WS2812B see https://cpldcpu.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/ For the actual Chip Timing. |
|
|
|
绝对最快的方式,使用内联汇编程序输出所有。根本不使用移位,也可能占用比C版本更少的代码空间。
以上来自于百度翻译 以下为原文 Absolute fastest way, using inline assembler for all the output. No shifting used at all. Probably occupies less code space than your C version too. //send one byte. parameter will come in W register. "Volatile" required to avoid "not used" warning //bits are sent starting bit-7 down to bit-0 void send_byte(volatile unsigned char data) { #asm BANKSEL _LATA btfss _WREG,7 goto bit7is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit7was1 bit7is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit7was1: btfss _WREG,6 goto bit6is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit6was1 bit6is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit6was1: btfss _WREG,5 goto bit5is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit5was1 bit5is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit5was1: btfss _WREG,4 goto bit4is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit4was1 bit4is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit4was1: btfss _WREG,3 goto bit3is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit3was1 bit3is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit3was1: btfss _WREG,2 goto bit2is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit2was1 bit2is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit2was1: btfss _WREG,1 goto bit1is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit1was1 bit1is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit1was1: btfss _WREG,0 goto bit6is0 bsf _LATA,0 ;long pulse to send 1 nop bcf _LATA,0 goto bit6was1 bit0is0: bsf _LATA,0 ;short pulse to send 0 bcf _LATA,0 bit0was1: #endasm } void ws2812_send(ws2812_ptr* led) { INTERRUPT_GlobalInterruptDisable(); INTERRUPT_PeripheralInterruptDisable(); send_byte(led->g); send_byte(led->r); send_byte(led->b); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); } |
|
|
|
可能是,但是它工作了,我的PIC有一半是空的。再加上更快意味着我必须添加NOP来减慢到正确的时间。我现在有3NOP来获得时间,所以我有一些余地。不幸的是,我很少再需要ASM。我的技能是Rusty。我以前在8052和x86天添加了ASM函数,但最近没有。真惭愧。因为其他原因,我很快就要旋转板子了,所以我可以试试你的代码。它可能对我没有帮助,因为原来的设计师每针放一个像素。所以我需要一个开关语句中的ASM的许多副本。
以上来自于百度翻译 以下为原文 qhb Could be, But it works and My PIC is Over Half empty. Plus Faster would mean I would have to add NOPs to slow it down to the Right timing. I have a 3 NOP to get the timing now, so I had a little head room. Unfortunately I seldom need ASM anymore. My skills are quite Rusty. I used to add ASM function in My 8052 and X86 days, but not lately. Shame on me. I need to spin the board for other reasons soon, so I may try out your code. It may not help me since the original designer put one pixel per pin. So I would need many copies of that ASM in a switch statement. |
|
|
|
你的PIC跑得有多快?你的评论“一个0应该高,然后低尽可能快”是不正确的,除非你运行你的PIC相当慢。存储每个位在一个数组可能采取额外的周期。为了消除所有的重复代码,使用一个宏时钟,一个位,并调用在你的循环:这些时间是64兆赫PIC18;鉴于延迟量,我猜它可以调整为32兆赫PIC16。
以上来自于百度翻译 以下为原文 How fast are you running your PIC? Your comment "a 0 should go high and then low as fast as possible" is not correct unless you're running your PIC pretty slow. Storing each bit in an array is probably taking extra cycles. And to get rid of all the repetitive code, use a macro that clocks out one bit, and invoke that in your loop: SEND_BIT(byte, 1U << 7); SEND_BIT(byte, 1U << 6); SEND_BIT(byte, 1U << 5); SEND_BIT(byte, 1U << 4);#define SEND_BIT(byte, mask) LED_DATA = 1; if (((byte) & (mask)) == 0) { _delay(3); LED_DATA = 0; _delay(11); } else { _delay(9); LED_DATA = 0; _delay(6); }Those timings are for 64 MHz PIC18; given the amount of delays, I'm guessing it could be adjusted for a 32 MHz PIC16. |
|
|
|
没问题,尼尔。那实际上是针对tgor152他并没有提到他正在运行的指令时钟速度,所以我的版本可能实际上太快了。
以上来自于百度翻译 以下为原文 No problem Neil. That was actually aimed at tgor152 He didn't mention what instruction clock speed he's running, so my version may in fact be too fast. |
|
|
|
假设OP说他没有可用的MSP。当必须处理这些烦人的WS2812部分时,我使用的另一种方法是PIC24+DMA+输出比较。没有CPU周期。
以上来自于百度翻译 以下为原文 That assumes an available MSSP which the OP says he doesn't have. Another approach I've used when having to deal with these annoying WS2812 parts is a PIC24 + DMA + output compare. No CPU cycles. |
|
|
|
我运行我的PIC在8兆赫我尝试内联汇编代码生病后我的结果
以上来自于百度翻译 以下为原文 I running my PIC at 8 MHz ill try the inline assembler code ill post my results |
|
|
|
我敢肯定你不能满足8兆赫的时间要求。
以上来自于百度翻译 以下为原文 I'm pretty sure you can't meet the timing requirements at 8 MHz. |
|
|
|
所以我继续尝试代码并用内联程序集获得了更好的结果,有一个小错误使它进入了无穷循环,但是得到了修复,结果接近完美,但是时间对于零位来说太长了,大约是530ns。为了安全起见,应该是500ns,而且字节之间的时间有点超过9us,基于这个网站的测试,这个时间有点长,可能导致重置
以上来自于百度翻译 以下为原文 So I went ahead and tried the code and got much better results with the inline assembly, There was a small error that made it go into infinite loop but that got fixed The results I'm getting are close to perfect however the timings are just a bit too long for a the zero bit is about 530ns where it should be 500ns to be safe also the time between bytes is a bit over 9us which based on the tests by this website is a bit too long and may cause a reset to occur Attached Image(s) |
|
|
|
只有小组成员才能发言,加入小组>>
4814 浏览 9 评论
1823 浏览 8 评论
1743 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
2949 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2055 浏览 5 评论
452浏览 1评论
1107浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
355浏览 0评论
260浏览 0评论
LAN9252使用SQI通信,进行数字复位后读BYTE_TEST异常
1777浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-19 13:49 , Processed in 1.194455 second(s), Total 83, Slave 68 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号