像65535 * 0.1这样的东西按预期工作,但是浮点数与来自内存的uint相乘会产生疯狂的值.我有一个函数读取ADC并返回一个uin16_t.有了这个值,我将它打印到一个4位数的LED显示屏上,工作正常.
将相同的值与1.0相乘会返回完全不同的东西(对于我的显示来说太大了,所以我真的不知道它是什么).
我的代码在下面,但争用的区域在main()的底部.任何帮助都会很棒.谢谢
main.c中:
#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include <stdint.h>#define BAUD 9600#include <util/setbaud.h>#define disP_BRIGHT_CMD 'z'#define disP_reset 'v'#define ADC_AVG 3 volatile uint8_t hi,lo;volatile uint16_t result; ISR(ADC_vect){ lo = ADCL; hi = ADCH; MCUCR &= ~_BV(SE); //Clear enable sleep } voID initSerial(voID){ // set baud rate UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; // set frame format UCSR0C |= (0x3 << UCSZ00); // 8n1 // set enable tx/rx UCSR0B = _BV(RXEN0) | _BV(TXEN0);}voID initADC(voID){ // AVCC and ADC0 ADMUX = _BV(REFS0); // Enable,div128,+ 1st setup ADCSRA |= _BV(ADEN)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0)|_BV(ADIE);}uint16_t readADC(voID){ uint16_t average=0; // Start Conversion ADCSRA |= _BV(ADSC); for (char i=0;i<ADC_AVG;i++) { MCUCR |= _BV(SE); ADCSRA |= _BV(ADSC); __asm volatile("sleep"); MCUCR &= ~_BV(SE); result = (hi<<8); result |= lo; average += result; } average /= ADC_AVG; return average; }voID sendByte(char val){ while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete UDR0 = val;}/* * Convert voltage to temperature based on a negative coefficIEnt for MAX6613 */uint16_t analogToTemp(uint16_t val){ uint16_t temp; //v = 5 * (val/1023.0); //temp = (1.8455 - (5.0*(val/1023.0)))/0.01123; temp = (1.8455 - (5.0*(val/1023.0)))*89; //temp = val * M_PI; //v = 5 * ( val/1024); //temp = (2 - v) * 89; return temp;}voID initdisplay(){ sendByte(disP_reset); sendByte(disP_BRIGHT_CMD); sendByte(0);}voID serialSegments(uint16_t val) { // 4 digit display sendByte(val / 1000); sendByte((val / 100) % 10); sendByte((val / 10) % 10); sendByte(val % 10); }int main(voID){ uint16_t calc=0,sense=0; DDRB |= _BV(DDB5); PORTB |= _BV(PORTB5); initSerial(); initADC(); initdisplay(); sei(); MCUCR |= (1 << SM0); // Setting sleep mode to "ADC Noise Reduction" MCUCR |= (1 << SE); // Sleep enable for(;;) { //PORTB ^= _BV(PORTB5); if (calc>=9999){ // I can't see the real value. Max val on display is 9999 //if (sense>=330){ PORTB |= _BV(PORTB5); } else { PORTB &= ~_BV(PORTB5); } sense = readADC(); //calc = sense*1.0; // refuses to calculate properly calc = analogToTemp(sense); // a bunch of zeroes //calc = 65535*0.1; // a-ok serialSegments(calc); _delay_ms(500); serialSegments(sense); _delay_ms(500); } return 0;}
Makefile文件:
# AVR-GCC MakefilePROJECT=Temp_displaySOURCES=main.cCC=avr-gccOBJcopY=avr-objcopyMMCU=atmega328pOSC_HZ=16000000ulOPTIMISATION=2PORT=/dev/ttyUSB0CFLAGS=-mmcu=${MMCU} -std=gnu99 -Wall -O${OPTIMISATION} -DF_cpu=${OSC_HZ} -lm -lc ${PROJECT}.hex: ${PROJECT}.out ${OBJcopY} -j .text -O ihex ${PROJECT}.out ${PROJECT}.hex avr-size ${PROJECT}.out$(PROJECT).out: $(SOURCES) ${CC} ${CFLAGS} -I./ -o ${PROJECT}.out ${SOURCES}program: ${PROJECT}.hex stty -F ${PORT} hupcl avrdude -V -F -c arduino -p m168 -b 57600 -P ${PORT} -U flash:w:${PROJECT}.hexclean: rm -f ${PROJECT}.out rm -f ${PROJECT}.hex
编辑:
好的,我在某种程度上简化了代码
#include <avr/io.h>#include <util/delay.h>#include <stdint.h>#define BAUD 9600#include <util/setbaud.h>#define disP_BRIGHT_CMD 'z'#define disP_reset 'v'voID initSerial(voID){ // set baud rate UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; // set frame format UCSR0C |= (0x3 << UCSZ00); // 8n1 // set enable tx/rx UCSR0B = _BV(TXEN0);}voID sendByte(char val){ while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete UDR0 = val;}voID initdisplay(){ sendByte(disP_reset); sendByte(disP_BRIGHT_CMD); sendByte(0);}voID serialSegments(uint16_t val) { // 4 digit display sendByte(val / 1000); sendByte((val / 100) % 10); sendByte((val / 10) % 10); sendByte(val % 10); }int main(voID){ uint16_t i=0,val; DDRB |= _BV(DDB5); initSerial(); initdisplay(); for(;;) { val = (uint16_t)(i++ * 1.5); serialSegments(i); _delay_ms(500); serialSegments(val); _delay_ms(500); if (val > 9999){ PORTB |= _BV(PORTB5); } else { PORTB &= ~_BV(PORTB5); } } return 0;}解决方法 非浮点浮点常量是double而不是float类型.
使用f后缀具有浮点字面值,例如0.1f
这可能会产生巨大的开销,因为像atmega8这样的MCU没有浮点单元,并且所有浮点运算都必须通过实现在固件中实现.
对于像atmega8这样的小型设备,通常会尝试避免使用浮动 *** 作,因为没有FPU,它们在cpu周期中非常昂贵.
现在没有理由实现不能正确翻译表达式,如:
calc = sense * 1.0;
当calc和sense是uint16_t类型时.
总结以上是内存溢出为你收集整理的使用AVR atmega8在C中出现意外的浮动行为全部内容,希望文章能够帮你解决使用AVR atmega8在C中出现意外的浮动行为所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)