我正在尝试组织我的UART库,并通过添加一些#define来稍微美化它,以便我可以在以后自定义它而不必深入研究代码,但我似乎无法得到以下一点代码工作:
#define FOSC 8000000
#define BAUDRATE 9600
#define BRGVAL (FOSC/2)/(16*BAUDRATE)-1
void uart_init(){
U1BRG = BRGVAL;
}
计算后BRGVAL变为25.0416667,因为它不是一个整数,当我将它分配给U1BRG时,我得到以下警告:
UART.c:在函数'uart_init'中:
UART.c:24:警告:表达式中的整数溢出
...而且代码根本无法在目标硬件上运行。 (如果我手动输入U1BRG = 25,它就像魅力一样)
有没有办法将该常量强制转换为整数以使编译器满意?
非常感谢, 哈姆扎。
答案 0 :(得分:24)
整数溢出意味着您已超过int值的上限,如果您收到此错误,则可能是32767。它与浮点无关;您指定的操作实际上是整数数学运算,因此无论如何都会丢弃除法的小数部分。
尝试这样的事情:
#define FOSC 8000000L
#define BAUDRATE 9600L
#define BRGVAL ((unsigned int)((FOSC/2)/(16*BAUDRATE)-1))
void uart_init(){
U1BRG = BRGVAL;
}
L后缀将这些常量转换为long
类型而不是int
类型。 (unsigned int)
强制转换为U1BRG的类型,并让编译器知道您了解long
值将适合unsigned int
,从而隐藏它可能向您抛出的任何警告。
通常情况下,沉默编译器警告是不好的做法,但在这种情况下,很明显,虽然您需要long
在计算中存储中间值,但最终结果将适合unsigned int
。
答案 1 :(得分:8)
我喜欢Philip的回答,但我认为更好的解决方案是减少公式并将宏更改为:
#define BRGVAL (FOSC/32/BAUDRATE-1)
这样做可以消除强制转换,因此如果选择低波特率导致分频器值对于16位int来说太大,编译器可以继续发出警告。
答案 2 :(得分:0)
我可能会用这个:
#define BRGVAL ((int)(FOSC/2)/(16*BAUDRATE)-1)
答案 3 :(得分:0)
您未能指出这一点,U1BRG的数据类型是什么?如果是int
,则按照显示
#define FOSC 8000000 #define BAUDRATE 9600 #define BRGVAL ((long)(FOSC/2)/(16*BAUDRATE)-1) void uart_init(){ U1BRG = BRGVAL; }
修改:修改此内容以考虑 Adam Liss 的评论,即unsigned int太小而无法保存结果宏,我已将其更改为long
... 感谢Adam为单挑......
希望这有帮助, 最好的祝福, 汤姆。
答案 4 :(得分:0)
从您的示例中不清楚U1BRG是全局变量还是#define'ed常量。在任何情况下,只需转换为整数即可:
U1BRG = (int)BRGVAL;