完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
大多数PIC18(如果不是全部)有一个惊人的寄存器称为PoStic(除此之外),但XC8似乎永远不会使用它。通过这个,MCU可以在一个指令中移动数据并自动增加一个16位指针。XC8使用大量的指令来做同样的操作:将地址复制到FSR对,移动数据并增加变量。乘以循环总数和……你得到一个非常低效的代码。有没有办法“强制”XC8使用这个寄存器?在汇编中必须编写所有代码?
以上来自于百度翻译 以下为原文 Most of the PIC18 (if not all) have an amazing register called POSTINC (among others), but XC8 seems to never use it. With this the MCU can move data and automatically increment a 16-bit pointer in a single instruction. Very useful for data transmit loops. XC8 uses a lot of instructions to do the same: copy the address to the FSR pair, move the data and increment the variable. Multiplying this for the total number of loops and...you get a very inefficient code. Is there a way to "force" XC8 to use this register (without having to write all the code in assembly)? |
|
相关推荐
11个回答
|
|
这是它处理间接寻址的方法,包括PoST或Pro,而不是在指令集中。没有什么了不起的,只有1个寄存器是低效的,这就是为什么我不再使用8位芯片。不知道强制编译器这样做,也许一个付费编译器会这么做。就像你的SAI一样。使用汇编程序。
以上来自于百度翻译 以下为原文 It's the way it handles indirect addressing including post/pre, just not in the instruction set. Nothing really amazing, it's inefficient only having 1 register, that's why I don't use 8bit chips anymore. Don't know about forcing the compiler to do that, maybe a paid compiler would do it. Like you said, use the assembler. |
|
|
|
您好,XC8编译器使用的是哪种许可证?自由模式或Pro模式。在自由模式下有很多优化,如果你还没有做过的话,有可能尝试2个月的最大优化。你不必在程序集中编写所有代码,只需要那些真正重要的部分。你可以完全编写一个函数。程序集,你可以在C中写一个函数条目和完成,并用一大块汇编代码填充它,或者你可以在C代码中加入汇编指令。注意,在C代码中加入汇编指令,如果没有C编译器知道发生了什么,可能会导致错误。例如改变FSR寄存器。R内容,而不是恢复原始值,可能会导致以下代码中的错误。这里是一个在C函数中封装的汇编代码的例子,它已经用于连接的交流测量和PIC16和PIC18上的RMS平均计算。
以上来自于百度翻译 以下为原文 Hi, Which kind of license for XC8 compiler are you using? Free or Pro mode. There are a lot of optimizations not done in Free mode, There is a possibility to try out maximum optimizations for 2 months, if you haven't done so already. You don't have to write all the code in assembly, only those parts where it really matter. You may write a function entirely in assembly, You may write a function entry and completion in C and fill it with a big block of assembly code, or you may put in assembly instructions in C code. Be careful, putting in assembly instructions in C code, without C compiler knowing what is going on, may cause errors. E.g. changing FSR register contents, and not restoring the original value, may cause error in following code. Here is an example of assembly code wrapped in a C function, it have been used in connection AC measurements and RMS average calculations on PIC16 and PIC18.: /* * PIC16, PIC18 * Calculate average from a running accumulator Avg = Avg >> 10; * Modified from code contributed on Microchip forum by "co_worker" * containing suggestions from "1and0" and "andig" * Microchip Forum http://www.microchip.com/forums/FindPost/848067 */ #include #include #define IN_ASM #ifndef Avgshift #define Avgshift 10 #endif /* * Unsigned integer shift * * Result = Arg >> 10; * * Parameters: * a = 24-bit unsigned integer accumulating samples. * * Return Value: * The function returns a 16-bit unsigned integer Result. * * Program Memory: * 20 instructions including call and return * * Execution Time: * 14 cycles excluding the call (prolog) and return (epilog). * * Remarks: * * * History: * 2016-05-04 - by Arne Bergseth "Mysil" */ uint16_t uShift_24_10(uint24_t Arg) { uint16_t Result = 0; /* Zero to make compiler happy, */ /* zeroing may be omitted if compiler warning is acceptable. */ #if defined(IN_C) result = a >> avgshift; #endif #if defined(IN_ASM) /* ? instructions, ? cycles, ? avg ? to be tested. */ /* * Ma. * * rh:rl = (au:ah:al >> 10) * */ #asm #ifdef _PIC18 #define rh (uShift_24_10@Result+1) #define rl (uShift_24_10@Result) #define au (uShift_24_10@Arg+2) #define ah (uShift_24_10@Arg+1) #define al (uShift_24_10@Arg) #elif _PIC14 || _PIC14E #define rh (uShift_24_10@Result+1)&0x7F #define rl (uShift_24_10@Result)&0x7F #define au (uShift_24_10@Arg+2)&0x7F #define ah (uShift_24_10@Arg+1)&0x7F #define al (uShift_24_10@Arg)&0x7F #endif BANKSEL(uShift_24_10@Arg) /* rh:rl = au:ah >> 1 Do 8 bit shift by picking bytes * then 1 bit shift by instruction */ bcf STATUS,0 /* clear the carry bit. */ #if (Avgshift == 8) /* Do 8 bit shift by picking bytes . */ movf au,W movwf rh movf ah,W movwf rl #elif (Avgshift > 8) /* then 1 bit shift by instruction. */ rrcf au,W /* Move from Au into W */ movwf rh /* store in Rh */ rrcf ah,W movwf rl #endif #if (Avgshift == 10) /* ru:rh:rl = ru:rh:rl >> 1 */ clrc /* one more rotation for 10 bit shift */ rrcf rh,F rrcf rl,F /* Shift into rl from the carry bit */ // rrcf rl,W ;/* may use W for this. */ #else movf rl,W /* start with low byte */ #endif #endasm #endif return Result; } Regards, Mysil |
|
|
|
|
|
|
|
我不认为XC8将编译一个16位的ChIPWink:我最后写了C和汇编的混合。效率提高了很多,但是代码可读性却呈指数下降,在编译器中重用FSR对的内容(在PRO模式下),在所有程序中找不到一个点。但是我知道手册警告这一点。下面是我做的一个例子。原始C代码:混合1:MIX2:用模拟器运行代码给出了以下结果(我必须注释“For(FLAG)”,因为SPI模块的这一部分在模拟器中没有实现):IFTXLEN=1(1循环):C:20 Cy;Mix1:18 Cy;Mix2:16 CyftxLeN=10(10个循环):C:146 Cy;Mix1:81 Cy;MIX2:70 Cy*Cy指令Cyrimix2是我能够做到的最优化的版本。最小化最后一次传输到结束的等待和下一次传输之间的指令数目。
以上来自于百度翻译 以下为原文 I don't think XC8 will compile for a 16-bit chip wink: Well I ended up writing a mix of C and assembly. The efficiency increases a lot, but code readability decreases exponentially. I could not find a single point in all program where the compiler reuses the contents of the FSR pair (in PRO mode). But I know the manual warns about this. Here is an example of what I did. Original C code: for (i = 0; i < txLen; i++) { PIR1bits.SSP1IF = 0; SSP1BUF = txBuffer; while (PIR1bits.SSP1IF == 0); } Mix 1: i = txLen + 1; #asm MOVLW low(_txBuffer) MOVWF FSR2, C MOVLW high(_txBuffer) MOVWF FSR2H, C; #endasm while (--i) { PIR1bits.SSP1IF = 0; #asm MOVFF POSTINC2, SSP1BUF; #endasm while (PIR1bits.SSP1IF == 0); } Mix2: if (txLen) { i = txLen; #asm MOVLW low(_txBuffer) MOVWF FSR2, C MOVLW high(_txBuffer) MOVWF FSR2H, C; #endasm PHY_CS = 0; #asm goto asm_send; #endasm do { while (SSP1STATbits.BF == 0); SSP1BUF; // Clear BF bit #asm asm_send: MOVFF POSTINC2, SSP1BUF; #endasm } while (--i); while (SSP1STATbits.BF == 0); } Running the code with the simulator gives the following results (I had to comment out the "while(flag);", because this part of the SPI module is not implement in the simulator): If txLen = 1 (1 loop): C: 20 cy; Mix1: 18 cy; Mix2: 16 cy If txLen = 10 (10 loops): C: 146 cy; Mix1: 81 cy; Mix2: 70 cy *cy - instruction cycle Mix 2 is the most optimized version that I was able to do. The number of instructions between the wait for the last transfer to finish and the next transfer are minimized. |
|
|
|
这可能不会节省很多时间,因为你在等待STAT标志。我会写整个FUNC。在ASM中使其更易于阅读。C和内联ASM的混合看起来不整洁。
以上来自于百度翻译 以下为原文 That may not save that much time since you are waiting for the STAT flag. I'd write the whole func. in asm to make it easier to read. A mix of C and inline asm does not look tidy. |
|
|
|
如果TXLEN是8位,DO-()循环可能会更好,所以试试这个:
以上来自于百度翻译 以下为原文 If txLen is 8-bit a do() loop might be better, so try this: asm("lfsr 2,_txBuffer"); i = txLen; do { PIR1bits.SSP1IF = 0; SSP1BUF = POSTINC2; while (PIR1bits.SSP1IF == 0); } while (--i); |
|
|
|
FIY,这可以用C语言编写,但是使用LFSR指令更有效。
以上来自于百度翻译 以下为原文 FYI, this #asm MOVLW low(_txBuffer) MOVWF FSR2, C MOVLW high(_txBuffer) MOVWF FSR2H, C; #endasm can be written in C as FSR2 = txBuffer; but use of the LFSR instruction is more efficient. |
|
|
|
这就解决了问题,感谢用户1和0!你回答了主要的问题。“强制”XC8使用PosiCin。我已经在MIX2版本中使用了DOE()循环,现在更可读(只有一个汇编指令):
以上来自于百度翻译 以下为原文 This solves the problem. Thanks user 1and0! You answered the main topic question. It is possible to "force" XC8 to use POSTINC. I'm already using the do() loop in the Mix2 version, and now is more readable (only one assembly instruction): if (txLen) { i = txLen; asm("LFSR 2,_txBuffer"); // FSR2 = txBuffer; goto sendPayload; do { while (SSP1STATbits.BF == 0); SSP1BUF; // Clear BF bit sendPayload: SSP1BUF = POSTINC2; // SSP1BUF = *txBuffer++; } while (--i); while (SSP1STATbits.BF == 0); } |
|
|
|
过去它是这样做的:这是从PICC V8列表文件中得到的。
以上来自于百度翻译 以下为原文 It used to do it back in the old days: 222 ; _buff loaded to fsr1 223 0078C0 C0D2 FFE1 movff ?_spi_write_sector,fsr1l 224 0078C4 C0D3 FFE2 movff ?_spi_write_sector+1,fsr1h 225 ;mmc.c: 84: u8 len; 234 ;mmc.c: 89: do { 243 ;mmc.c: 94: SSPBUF = *buff++; 244 0078D8 CFE6 FFC9 movff postinc1,4041 ;volatile 245 ;mmc.c: 95: } while (--len); That's from a PICC v8 list file. |
|
|
|
不要认为GOTO是必要的。试试这个:
以上来自于百度翻译 以下为原文 Don't think the GOTO is necessary. Try this: if (txLen) { i = txLen; asm("LFSR 2,_txBuffer"); // FSR2 = txBuffer; do { SSP1BUF = POSTINC2; // SSP1BUF = *txBuffer++; while (SSP1STATbits.BF == 0); SSP1BUF; // Clear BF bit } while (--i); } |
|
|
|
那样的话,我在最后一次传输之后会失去几个周期。不要介意Goto指令。我并没有真正使用它,因为SSP1BUF是在代码到达这个部分之前编写的。在这个例子中我用它来显示速度优化。
以上来自于百度翻译 以下为原文 That way I’m losing a couple cycles after the last transmission. Don’t mind the goto instruction. I’m not really using it, because SSP1BUF is written before the code reaches this part. I used it in this example just to show speed optimization. |
|
|
|
只有小组成员才能发言,加入小组>>
5244 浏览 9 评论
2035 浏览 8 评论
1955 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3209 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2260 浏览 5 评论
779浏览 1评论
672浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
598浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
682浏览 0评论
579浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 11:02 , Processed in 1.547456 second(s), Total 98, Slave 81 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号