完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
大家好,我将32位数据发送到一些LED驱动程序,不能使用SPI端口,所以我只使用两个I/O引脚用于CLK和数据。我无法找到一个好的方法来根据数据变量中的位设置数据端口PIN。我想先从第31位开始,但我找不到一个宏,它测试了一个给定变量和位号类似的宏:定义了位集(var,BITNO)((var)=1UL& lt;;(BITNO))定义了BITClR(var,BITNO)((var)&=(1UL & lt;;(BITNO))),我看到了一个名为BITTEST(VAR,BI)。TNO)某处,但找不到它。其他任何想法也将被赞赏。谢谢!
以上来自于百度翻译 以下为原文 Hello all, I'm sending 32bits of data to some LED drivers and can't use an SPI port, so I'm using just two I/O pins for clk and data. I can't figure out a good way to set the data port pin based on the bit in the data variable. I want to start with bit 31 first. I have seen, but can't find a macro that tests a bit given the variable and bit number similar to these: #define bitset(var, bitno) ((var) |= 1UL << (bitno)) #define bitclr(var, bitno) ((var) &= ~(1UL << (bitno))) I have seen one called bittest(var, bitno) somewhere but can't find it. Any other idea would be appreciated as well. Thanks ;) Don |
|
相关推荐
19个回答
|
|
MSB的测试数,即如果(数字和0x8000)和输出位相应,然后左移“数字”。PS:整个“大爆炸”从32位看起来似乎有点过分。
以上来自于百度翻译 以下为原文 Test number for MSB, i.e. if(number & 0x80000000) and output bit accordingly, then left shift "number". PS: entire "big bang" from just 32bits seems to be a bit too exxagerated |
|
|
|
β位测试(VAR,BITNO)((var),(1UL&L.&L.;(BITNO))和GT;0)虽然我在8位MCU上实现了不同:将32位有价值的分割成4个单个字节(例如使用一些联合),一个接一个地字节移位,并且(未签名!)移位。位掩码每轮一个右键-用0B100000 U重新加载每个字节的开始。
以上来自于百度翻译 以下为原文 #bittest(var,bitno) (((var) & (1ul << (bitno))) > 0) Though I'd implement it differently on an 8-bit MCU: split the 32 bit valuable into 4 single bytes (eg. using some union), pr9cessing the bytes one after the other and shifting the (unsigned!) bit mask right by one each round - reloading with 0b1000000u for the start of each byte. |
|
|
|
+ 1用于移位数据或位掩码。从一个变量中生成一个掩码是非常低效的。我也建议每次做四个8位,而不是每次32位。
以上来自于百度翻译 以下为原文 +1 for shifting the data or a bitmask. It is extremely inefficient to generate a mask on the fly from a variable. I'd also recommend doing it as four lots of 8 bits, rather than all 32 bits every time. |
|
|
|
|
|
|
|
我指望优化,但实际上一次处理一个字节会更快,可能会牺牲代码的可移植性。
以上来自于百度翻译 以下为原文 I was counting on Optimizations but indeed handling one byte at a time will be faster, maybe at some expense of portability of code etc. |
|
|
|
也许考虑在同步模式下使用USAT并首先将数据移出LSB。正如已经提到的,C中的位操作是低效的,所以使用汇编语言封装在C函数中。您选择的方法取决于需要优化、通过放置、传输速度或硬件。重新资源。
以上来自于百度翻译 以下为原文 Perhaps consider using the USART in synchronous mode and shift the data out LSB first. As has been mentioned, bit manipulations in C are inefficient so use assembly language wrapped in a C function. The method you select depends on what needs to be optimized, through put, transmission speed or hardware resources. |
|
|
|
谢谢你的建议。我想我会使用'BITTest'。我不是真的移动32位数据变量,但是我要测试每一个比特,从B31开始。它们是32位变量的原因是因为每个层要转移到LED驱动器(有5个层)被存储在一个5x5显示缓冲器中。位B7至B5不持有任何LED信息。将它们放入32位变量,然后将它们移位5位,将所有数据打包成一个变量。它也让我用相同的功能来完成每一层的操作,我只是把它显示给显示缓冲器的索引,然后我用同样的函数把数据移出I/O引脚。我会张贴一些代码…谢谢你的建议;
以上来自于百度翻译 以下为原文 Thanks for the ideas. I think I will use the 'bittest'. I'm not really shifting the 32 bit data variable, but I am going to test each bit, starting with b31. The reason they are in a 32bit variable is because each layer to be shifted out to the LED drivers (there are 5 layers) is stored in a 5x5 display buffer. Bit b7 to b5 do not hold any LED info. Putting them into the 32bit variable then shifting them left 5 bits, packs all the data into one variable. It also lets me use same function to do this with each layer, I just send it the index of the Display buffer and then I use same function to 'shift' the data out the I/O pin. I'll post some of the code .. *************** Global Data Declarations *************************************************************************/ // declare global data variables here including buffers APP_STATES app_state; // The application's current state APP_DISPLAY_STATES display_state; // The state of the multiplex display uint8_t DrawBuf[5][5]; // Buffer for drawing LEDs before display, first index=layer, second=LED uint8_t DispBuf[5][5]; // Buffer for the Multiplex display, first index=layer, second=LED uint32_t ShiftData; // Buffer for data to shift to LED drivers bit CopyBuf; // Flag bit to indicate we need to copy DrawBuf to DisplayBuf /******************************************************************************************************************* * Function: void APP_TMR0InterruptHandler(void); * Overview: handles Interrupts from TMR0 * PreCondition: None *******************************************************************************************************************/ void APP_TMR0InterruptHandler(void) { if (CopyBuf) { for (uint8_t x=0; x<5; x++) { for (uint8_t y=0; y<5; y++) { DispBuf[x][y] = DrawBuf[x][y]; } } CopyBuf = 0; } switch (display_state) { case L1: { APP_ShiftLayerData(0); // shift Layer 1 data out to LED drivers L5_SetLow(); // turn off previous Layer Latch_SetHigh(); // LED driver Latch (LE/DM1) HIGH __delay_us(1); // delay for Latch (LE/DM1) pulse width Latch_SetLow(); // LED driver Latch (LE/DM1) LOW L1_SetHigh(); // turn on this Layer display_state = L2; // next display state break; } case L2: { APP_ShiftLayerData(1); // shift Layer 2 data out to LED drivers L1_SetLow(); // turn off previous Layer Latch_SetHigh(); // LED driver Latch (LE/DM1) HIGH __delay_us(1); // delay for Latch (LE/DM1) pulse width Latch_SetLow(); // LED driver Latch (LE/DM1) LOW L2_SetHigh(); // turn on this Layer display_state = L3; // next display state break; } case L3: { APP_ShiftLayerData(2); // shift Layer 3 data out to LED drivers L2_SetLow(); // turn off previous Layer Latch_SetHigh(); // LED driver Latch (LE/DM1) HIGH __delay_us(1); // delay for Latch (LE/DM1) pulse width Latch_SetLow(); // LED driver Latch (LE/DM1) LOW L3_SetHigh(); // turn on this Layer display_state = L4; // next display state break; } case L4: { APP_ShiftLayerData(3); // shift Layer 4 data out to LED drivers L3_SetLow(); // turn off previous Layer Latch_SetHigh(); // LED driver Latch (LE/DM1) HIGH __delay_us(1); // delay for Latch (LE/DM1) pulse width Latch_SetLow(); // LED driver Latch (LE/DM1) LOW L4_SetHigh(); // turn on this Layer display_state = L5; // next display state break; } case L5: { APP_ShiftLayerData(4); // shift Layer 5 data out to LED drivers L4_SetLow(); // turn off previous Layer Latch_SetHigh(); // LED driver Latch (LE/DM1) HIGH __delay_us(1); // delay for Latch (LE/DM1) pulse width Latch_SetLow(); // LED driver Latch (LE/DM1) LOW L5_SetHigh(); // turn on this Layer display_state = L1; // next display state } } } /******************************************************************************************************************* * Function: void APP_ShiftLayerData(uint8_t index); * Overview: shift layer data into common variable to send to LED drivers * Argument: Index of DispayBuffer to shift out to LED driver *******************************************************************************************************************/ void APP_ShiftLayerData(uint8_t index) { ShiftData = 0; // clear shift data buffer ShiftData = DispBuf[index][0]; // LEDs 1-5 ShiftData = (ShiftData<<5); // shift data 5 bits left ShiftData = (ShiftData | DispBuf[index][1]); // LEDs 6-10 ShiftData = (ShiftData<<5); // shift data 5 bits left ShiftData = (ShiftData | DispBuf[index][2]); // LEDs 11-15 ShiftData = (ShiftData<<5); // shift data 5 bits left ShiftData = (ShiftData | DispBuf[index][3]); // LEDs 16-20 ShiftData = (ShiftData<<5); // shift data 5 bits left ShiftData = (ShiftData | DispBuf[index][4]); // LEDs 21-25 APP_ShiftData(); // shift data out to LED drivers } /******************************************************************************************************************* * Function: void APP_ShiftData(void); * Overview: shifts 32 bits of data out to LED drivers * PreCondition: None *******************************************************************************************************************/ void APP_ShiftData(void) { // need to add function here to set data IO pin and toggle clk IO pin } Thanks for the suggestions ;) |
|
|
|
|
|
|
|
也许考虑在同步模式下使用USAT并首先将数据移出LSB。正如已经提到的,C中的位操作是低效的,所以使用汇编语言封装在C函数中。您选择的方法取决于需要优化的内容。通过PIT、传输速度或硬件资源,我被PIN任务所困扰。这是PIC在一个原板上,它与原来的14引脚PIC16F68 8接口。我增加了一些设计的能力,使用了一对MSGQ5A来添加3D图形音乐显示。原来的设计是在这里。&,HTTP://PiPrj.S.Org.UK/PrimeSt/Lc/Realth.HMME添加。& HTTPS://www. Youtub。E.COM/手表?V= 3RKIKQVQNU这是用PIC16F68 9,我正在改变它使用PIC16F1829和使用C这次。
以上来自于百度翻译 以下为原文 Perhaps consider using the USART in synchronous mode and shift the data out LSB first. As has been mentioned, bit manipulations in C are inefficient so use assembly language wrapped in a C function. The method you select depends on what needs to optimized. Through put, transmission speed or hardware resources. I'm stuck with the pin assignments. This is PIC is on a proto board that 'interfaces' with the original 14 pin PIC16F688. I've added some capability to the design, uses a couple of MSGQ5A's to add 3D graphic music display. Original design is here -> http://picprojects.org.uk/projects/lc/index.htm My additions -> https://www.youtube.com/watch?v=3RKIeRqvQnU this was done with PIC16F689, I'm changing it to use the PIC16F1829 and using C this time. |
|
|
|
谢谢你的建议。我想我会用“BITTEST”,所以在我们说了之后,你还是选择了最低效的方式?
以上来自于百度翻译 以下为原文 Thanks for the ideas. I think I will use the 'bittest'. So after everything we said, you still elected to go with the most inefficient way? |
|
|
|
谢谢你的建议。我想我会用“BITTEST”,所以在我们说了之后,你还是选择了最低效的方式?好的,我能做得更有效率吗?比这个?我假设你已经看到了我的文章和其他代码。
以上来自于百度翻译 以下为原文 Thanks for the ideas. I think I will use the 'bittest'. So after everything we said, you still elected to go with the most inefficient way? Ok, so could I do it more efficient .. /******************************************************************************************************************* * Function: void APP_ShiftData(void); * Overview: shifts 32 bits of data out to LED drivers * PreCondition: None *******************************************************************************************************************/ void APP_ShiftData(void) { for (int x=31; x<0; x--) { if (bittest(ShiftData, x)) { Sout_SetHigh(); } else Sout_SetLow(); NOP(); CLK_SetHigh(); NOP(); NOP(); CLK_SetLow(); } } Than this? I am assuming you have seen my post with the rest of the code. ;) |
|
|
|
BITTestin必须从一个变量“即时”生成一个位掩码。这就是我们所说的最低效的方法。测试一个常数位(例如位31)更有效,并且在每次测试后把数据移一点。还有可能的改进,这就是我们所要做的。以上讨论。
以上来自于百度翻译 以下为原文 bittest has to generate a bit mask from a variable "on the fly". That is what we are saying is the most inefficient way to do it. It's far more efficient to test a constant bit (e.g. bit#31), and shift the data left one bit after each test. There are further improvements possible, which is what we were discussing above. |
|
|
|
以上来自于百度翻译 以下为原文 void APP_ShiftData(void) { unsigned long sr = ShiftData; // copy into a working register unsigned char count=32; // loop 32 times do { if(sr & 0x80000000) Sout_SetHigh(); // if bit 31 was high else Sout_SetLow(); // if bit 31 was low NOP(); //short delay. Probably not needed as Sout_SetXXX() will cause a delay anyway. CLK_SetHigh(); sr <<= 1; //move working register left one bit. Also gives short delay CLK_SetLow(); } while (--count); //loop until count reaches zero } |
|
|
|
那你为什么要把它们打包成32个字,把那些乱七八糟的东西转移出去?为什么不做一个函数来改变每个数组元素的重要部分。此外,为什么使用全局变量来复制数据,而不是使用数组(指针值,即函数变量)?我会做一个测试程序,打印出所有数组元素的所有有意义的位,然后从上到下,设计可以是这样的:现在,SHIVT5X5看起来像什么?也许是这样的:我这样做了,通过使用不同的掩码值,它可以从每个字符中移出任何位数(1-8)。接下来,SHIFTTIOUT函数如何使用掩码?请注意,我的函数有打印语句,因为要测试,我将打印位值而不是实际移位它们。可以简单地输出的函数可以是这样的:数组编号1:行0:0 0 0 0 0 1 0 0 0 1 0 1,x,1,1,1:0、1、1、1、0、1、0、0、0、0、1、0、1、0、0、0、1、2、2、2、1、2、2、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、2、1、2、2、1、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、3、0、0、0之间的关系;0、0、0、0、0、0、1、0、0、0、1、0、0、1、1、1、1、2、1、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、2、1、2、1、2、1、2、2、2、2、1、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、2、1、2、2、2、1、2、2、2、2、1、2、2、2、2、1、2、2、2、2、1、2、2、2、2、1、2、2、2、2、1、2、2、2、2、1、2、2、2、1、2、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、1、2、2、2、1、2、2、1、2、2、2Y你需要在程序中的任何一个点上——给它一个指向那个行的指针,正如我所展示的。我只是扔进去让测试更完整(对我来说更简单)。问候,戴夫
以上来自于百度翻译 以下为原文 Then why the heck do you pack them into a 32-bit word and shift that mess out? Why not just make a function that shifts out the significant parts of each array element. Furthermore, why the heck do you use global variables that you copy stuff into instead of using arrays (pointer values, that is) as function arguments? I'll make a test program that prints out all of the meaningful bits of all of the array elements for a couple of arrays. From the top down, the design can go something like this: /* In main() or wherever you need them to be. * I'll give them specific initial variables for testing * * Furthermore, instead of actually shifting them out, I'll * make a "fake" shift function that prints the bit values * in the order in which they will actually be shifted */ uint8_t ar1[5][5] = { {0x01, 0x02, 0x03, 0x04, 0x05}, {0x06, 0x07, 0x08, 0x09, 0x0A}, {0x0B, 0x0C, 0x0D, 0x0E, 0x0F}, {0x10, 0x11, 0x12, 0x13, 0x14}, {0x15, 0x16, 0x17, 0x18, 0x19} }; uint8_t ar2[5][5] = { {0x1A, 0x1B, 0x1C, 0x1D, 0x1E}, {0x1F, 0x00, 0x01, 0x02, 0x03}, {0x04, 0x05, 0x06, 0x07, 0x08}, {0x08, 0x0A, 0x0B, 0x0C, 0x0D}, {0x0E, 0x0F, 0x10, 0x11, 0x12} }; printf("Array number 1:n"); shift5x5(ar1); printf("nArray number 2:n"); shift5x5(ar2); Now, what does the shift5x5 look like? Maybe something like this: void shift5x5(uint8_t array[][5]) { int i, j; /* Will shift out five least significant bits of each array element */ uint8_t mask = 0x10; for (i = 0; i < 5; i++) { printf("Row %d: ", i); for (j = 0; j < 5; j++) { shift_out(array[j], mask); } printf("n"); } } I made it so that, by using a different mask value, it can shift out any number of bits (1-8) from each character. Next, how does the shift_out function use the mask? void shift_out(uint8_t value, uint8_t mask) { for (; mask; mask >>= 1) { output_bit((mask & value) != 0); } } Note that my functions have print statements since for testing, I'll print the bit values rather than actually shift them. The function that simulates the shift can be simply /* A "fake" output shift function that prints the bit values. * Actual code sets output to the bit value and toggles the * clock to active level and back to inactive. */ void output_bit(uint8_t bvalue) { printf("%d ", bvalue); } Output can look something like this: Array number 1: Row 0: 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 Row 1: 0 0 1 1 0 0 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 0 1 0 Row 2: 0 1 0 1 1 0 1 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 1 1 1 Row 3: 1 0 0 0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1 1 1 0 1 0 0 Row 4: 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1 0 0 1 Array number 2: Row 0: 1 1 0 1 0 1 1 0 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 0 Row 1: 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 Row 2: 0 0 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 1 1 0 1 0 0 0 Row 3: 0 1 0 0 0 0 1 0 1 0 0 1 0 1 1 0 1 1 0 0 0 1 1 0 1 Row 4: 0 1 1 1 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 1 1 0 0 1 0 Maybe you don't need the shift5x5 function at all (just use shift_out for the row of whatever array you need at any given point in the program--feed it the pointer to that row, as I showed). I just threw it in to make testing more complete (and simpler for me to change). Regards, Dave |
|
|
|
还有一个帖子,我提到,我只使用5位的每一个字节的显示缓冲区。包装成一个单一的变量完成,也允许我使用相同的函数代码的五个层中的每一个。只需要发送显示缓冲区的索引。
以上来自于百度翻译 以下为原文 There was another post where I mentioned that I am only using 5 bits of each byte of my Display Buffer. Packing them into a single variable accomplished that and also allowed me to use the same function code for each of the five layers. Only had to send index of the display buffer. |
|
|
|
好的,我可以看到,也许甚至不用复制SHIFT数据到工作寄存器。不知道为什么它会比我的效率更高。你能解释一下吗?
以上来自于百度翻译 以下为原文 Ok, I can see that, maybe don't even have to copy ShiftData to working register. Not sure why it would be more efficient than the way I did. Can you explain? |
|
|
|
我一直在尝试。BITTEST宏从一个变量“即时”生成一个掩码。没有PIC指令来做这件事,所以它必须使用一个循环来完成,这个循环会在你的循环中每一次都有很多指令。这是非常低效的。测试一个已知的位需要一个指令。你可以学到很多东西,但是看看编译器输出的汇编代码,看看它为实现你的代码所做的事情。你使用的越多,它的效率就越低。
以上来自于百度翻译 以下为原文 I've been trying to. The BitTest macro is generating a mask from a variable "on the fly". There is no PIC instruction to do this, so it has to do it using a loop, which will take many instructions, every single time around your loop. That's hugely inefficient. Testing a single known bit takes a single instruction. You can learn a lot just but looking at the assembly code output by the compiler, and see what it has to do to implement your code. The more indirections you use, the less efficient it becomes. |
|
|
|
“BITTEST宏从一个变量中生成一个”即时“的掩码”,没有PIC指令这样做,“这是因为在指令”BTFSC PoTa,5“,比特是恒定的吗?我将不得不查看生成的代码来查看这个“即时”,但是我看到了你所说的,并将使用你的建议。感恩节
以上来自于百度翻译 以下为原文 "The BitTest macro is generating a mask from a variable "on the fly". There is no PIC instruction to do this," Is that because in the instruction "btfsc PORTA, 5", the bit is constant? I will have to look at the generated code to see this "on the fly", but I see what your are saying and will use your suggestion. Thanks Don |
|
|
|
是的,没有类似于“BTFSC PATA,W”的指令。
以上来自于百度翻译 以下为原文 Yes. There is no instruction similar to "btfsc PORTA, W" |
|
|
|
只有小组成员才能发言,加入小组>>
4825 浏览 9 评论
1831 浏览 8 评论
1749 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
2956 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2060 浏览 5 评论
461浏览 1评论
1111浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
364浏览 0评论
263浏览 0评论
LAN9252使用SQI通信,进行数字复位后读BYTE_TEST异常
1800浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-26 11:21 , Processed in 1.084160 second(s), Total 61, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号