最近在项目中用到了holtek厂商的HT45F24A和BA45F5650两款单片机。
用的开发工具是HT-IDE3000,烧录软件是HOPE3000。
这两款单片机都是8位的单片机,支持寄存器位操作。
HT45F24A单片机不带UART串口,要想实现串口功能,只能自己用定时器操作GPIO来模拟UART发送时序。
BA45F5650单片机带UART串口,可直接使用。
IDE里面支持float和double浮点类型,但是却没有<stdio.h>头文件,不支持printf函数,sprintf函数,编译器不支持stdarg可变参数函数,所以也没法自己实现printf函数。
IDE里面有字符串转浮点数的函数,却没有浮点数转字符串的函数,这个功能得自己编程实现。
另外,IDE里面的float是3/4精度浮点数(3字节),double是单精度浮点数(4字节)。
而电脑上的float是单精度浮点数(4字节),double是双精度浮点数(8字节)。
程序下载链接:https://pan.baidu.com/s/1SLjIJdzTKRk06zur2QshhQ?pwd=m8ay
先在电脑上用Visual Studio 2010实现4字节单精度浮点数转字符串的功能。
双精度浮点数double和四精度浮点数long double转字符串已经有人写出来了:
https://www.cnblogs.com/carekee/articles/3124256.html
只需要参照他的思想,写一个单精度浮点数float的转换函数就可以了。
【ftoa.h】
#pragma once#define FTOA_PRECISION 8 // 转换时保留的有效数字位数
#define FTOA_PRECISION_MAX 1e8 // 必须等于10^FTOA_PRECISION
typedef uint32_t ftoa_fixnum_t; // 此类型至少要能保存10*FTOA_PRECISION_MAX那么大的数#define FLOAT_VAL(var) (*(float *)&(var))
#define FLOAT_HEXVAL(var) (*((uint32_t *)&(var)))
#define FLOAT_SIGN(var) (FLOAT_HEXVAL(var) >> 31) // 1bit
#define FLOAT_CLEARSIGN(var) (FLOAT_HEXVAL(var) & 0x7fffffff)
#define FLOAT_EXPONENT(var) (((FLOAT_HEXVAL(var) >> 23) & 0xff) - 127) // 8bits
#define FLOAT_MANTISSA(var) (FLOAT_HEXVAL(var) & 0x7fffff) // 23bits
#define MAKE_FLOAT_HEXVAL(s, e, m) ((((uint32_t)(s) & 1) << 31) | (((uint32_t)((e) + 127) & 0xff) << 23) | ((uint32_t)(m) & 0x7fffff))
#define MAKE_FLOAT(f, s, e, m) FLOAT_HEXVAL(f) = MAKE_FLOAT_HEXVAL((s), (e), (m))char *ftoa(float value);
char *ltoa(long value);
【ftoa.c】
#include <stdint.h>
#include <string.h>
#include "ftoa.h"static const float float_table[31] = {1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f, 1.0e11f, 1.0e12f, 1.0e13f, 1.0e14f, 1.0e15f, 1.0e16f, 1.0e17f, 1.0e18f, 1.0e19f, 1.0e20f, 1.0e21f, 1.0e22f, 1.0e23f, 1.0e24f, 1.0e25f, 1.0e26f, 1.0e27f, 1.0e28f, 1.0e29f, 1.0e30f, 1.0e31f
};
static const float float_table_2[1] = {1.0e32f};char *ftoa(float value)
{static char str[50];char *p = str;float num;ftoa_fixnum_t fixnum;int16_t e, k, a, b, i;uint8_t negative = FLOAT_SIGN(value);/* 总体思想 */// (1) 如果浮点数的整数部分能够放进一个整型变量里面, 直接把这个整型变量的值转换成十进制字符串就行了// (2) 如果浮点数的整数部分太大, 超过了整型变量的取值范围, 则除以10^k, 就能成功放进整型变量里面了, 然后把整型变量转换成十进制字符串, 字符串末尾要添0// (3) 如果浮点数的整数部分为0, 只有小数部分, 那么乘以10^(-k), 整数部分就不是0了, 放进整型变量后就可以转换成字符串了, 再在合适的位置点上小数点// 为了使结果包含尽可能多的有效数字, 应该正确选择k值, 使整数部分能够尽可能占满整型变量的最大存储空间// 变量e决定了最后在字符串的什么位置点上小数点/* 第一步: 先把|value|改写成num*(10^k)的形式 */// |value|=num*(10^k), 其中k=32*a+b// num的整数部分的大小有如下两个要求:// (1) 必须要在ftoa_fixnum_t类型能表示的数值范围内, 并且不能为负数// (2) 数位尽可能多, 最好是有FTOA_PRECISION位数// 将二进制指数转化成十进制指数// 设2^x=10^e, 则e=lg(2^x)=xlg2 (x就是浮点数里面那个二进制指数)// lg2是一个无理数, 可以取近似值19728/65536e = FLOAT_EXPONENT(value);if (e == -127){if (!negative)strcpy(str, "0");elsestrcpy(str, "-0");return str;}else if (e == 128){if (FLOAT_MANTISSA(value) == 0){if (!negative)strcpy(str, "inf");elsestrcpy(str, "-inf");}else{if (!negative)strcpy(str, "nan");elsestrcpy(str, "-nan");}return str;}e = ((int32_t)e * 19728) / 65536; // 由于lg2的值不精确, 所以这里的e值是近似值, 但是没有关系, 只要整型变量fixnum能放得下num, 就不会转换出错// 根据e的值确定k值, 使num的数位尽可能多k = -(FTOA_PRECISION - (e + 1)); // e是科学计数法的指数, 那e+1就是位数, 例如10^4是5位数// 再根据k值和value值确定num值// k/32=a......b// num=|value|/(10^k)// =|value|/[10^(32*a+b)]// =|value|/[10^(32*a)]/(10^b)FLOAT_HEXVAL(num) = FLOAT_CLEARSIGN(value); // 取浮点数绝对值if (k > 0){a = k / 32;b = k % 32;if (a != 0)num /= float_table_2[a - 1];if (b != 0)num /= float_table[b - 1];}else if (k < 0){a = (-k) / 32;b = (-k) % 32;if (a != 0)num *= float_table_2[a - 1];if (b != 0)num *= float_table[b - 1];}// num的整数部分四舍五入// 0.4+0.5=0.9=>0, 0.5+0.5=1.0=>1, 0.6+0.5=1.1=>1num += 0.5f;// 如果num的位数<FTOA_PRECISION, 可以在前面补0, 补够FTOA_PRECISION位数// 但如果发现num>=FTOA_PRECISION_MAX, 那么num的位数就不是<=FTOA_PRECISION, 而是=FTOA_PRECISION+1// 位数多了一位, 说明前面的e值太小了, 导致k的大小不合适if (num >= FTOA_PRECISION_MAX){// e的值增加1, 然后k的值也增加1e++;k++;// 为了使等式|value|=num*(10^k)仍然成立, num的值要缩小10倍才行num /= 10;}// num是由|value|/(10^k)得来的, 理论上无论k取几, num的值都是value的十进制小数位// 比如num=12345678901234567890, 当k=15时, num=12345; 当k=12时, num=12345678// 就算是前面e的值因lg2不精确没算准确, 也不可能出现num不是value的十进制小数位的情况, 搞清楚这一点非常重要// k的值又是由e的值得来的, 所以小数点是不可能点错位置的// 只不过k的大小如果不合适, 那么num的大小就会太大或者太小, 没法存到fixnum整型变量里面, 就没法转成字符串/* 第二步: 取num的整数部分, 存到fixnum整型变量中, 舍弃小数部分 */
#if 0// (方法1)fixnum = (ftoa_fixnum_t)num;
#else// (方法2)// 请注意在浮点数标准格式里面, 尾数是有小数点的, 小数点在尾数的最左侧, 小数点左边还有一个隐藏的1fixnum = FLOAT_MANTISSA(num) | (1ul << 23); // 取尾数, 补上小数点前隐藏的1, 然后去掉小数点i = FLOAT_EXPONENT(num) - 23; // 取指数 (因为上一步去掉了小数点, 导致原数扩大了2^23倍, 所以取出来的指数要减23)// 乘上2的(指数-23)次方if (i > 0)fixnum <<= i; else if (i < 0)fixnum >>= -i;
#endif/* 第三步: 根据e值和fixnum值输出字符串 */// 小数点的位置应该点在fixnum数值从左边数第e+1位数的后面if (negative)*p++ = '-';if (e + 1 < 1){// 如果e + 1 < 1, 就要在前面添0*p++ = '0';*p++ = '.';while (e + 1 < 0){*p++ = '0';e++;}// 后面只有数字, 不再添加小数点i = FTOA_PRECISION;}else if (e + 1 < FTOA_PRECISION){// 小数点在数字中间i = FTOA_PRECISION + 1;}else{// 没有小数点, 数字末尾可能要补0i = e + 1;}p[i--] = '\0';while (i >= 0){if (i >= FTOA_PRECISION && e + 1 >= FTOA_PRECISION)p[i--] = '0';else{if (i == e + 1 && i != 0)p[i--] = '.';p[i--] = '0' + fixnum % 10;fixnum /= 10;}}/* 第四步: 去掉小数点末尾多余的0 */if (e + 1 < FTOA_PRECISION){i = FTOA_PRECISION;if (p[i] == '\0')i--;while (i >= 0 && p[i] == '0'){p[i] = '\0';i--;}if (i >= 0 && p[i] == '.')p[i] = '\0';}return str;
}char *ltoa(long value)
{static char str[12];char temp;uint8_t i, n, start = 0;if (value == 0){str[0] = '0';str[1] = '\0';}else{// 正数的最大值是2147483647// 负数的绝对值的最大值是2147483648// 负数的表示范围更大, 所以把所有的正数都转换成负数if (value < 0){str[0] = '-';start = 1;}elsevalue = -value;// 从左到右依次存放低位到高位for (i = start; value != 0; i++){str[i] = '0' + (-(value % 10));value /= 10;}str[i] = '\0';// 字符串倒序: 高位移到左边, 低位移到右边n = i - start;for (i = 0; i < n / 2; i++){temp = str[start + i];str[start + i] = str[start + n - i - 1];str[start + n - i - 1] = temp;}}return str;
}
【main.c】
#include <stdint.h>
#include <stdio.h>
#include "ftoa.h"int main(void)
{float f;MAKE_FLOAT(f, 0, 13, 7 << 20);printf("1.875*(2^13)=%s\n", ftoa(f));printf("%s\n", ftoa(-0.00075f));printf("%s\n", ftoa(-3.1415926f));printf("%s\n", ftoa(-13.1415926f));printf("%s\n", ftoa(0.0012345678f));printf("%s\n", ftoa(0.012345678f));printf("%s\n", ftoa(0.12345678f));printf("%s\n", ftoa(1.2345678f));printf("%s\n", ftoa(12.345678f));printf("%s\n", ftoa(123.45678f));printf("%s\n", ftoa(1234.5678f));printf("%s\n", ftoa(12345.678f));printf("%s\n", ftoa(123456.78f));printf("%s\n", ftoa(1234567.8f));printf("%s\n", ftoa(12345678.0f));printf("%s\n", ftoa(123456789.0f));printf("%s\n", ftoa(123456789012.0f));printf("%s\n", ftoa(1.23e38f));printf("%s\n", ftoa(-1.23e-38f));MAKE_FLOAT(f, 0, -127, 0);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 0, -127, 7 << 20);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 1, -127, 0);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 1, -127, 7 << 20);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 0, 128, 0);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 0, 128, 7 << 20);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 1, 128, 0);printf("%f %s\n", f, ftoa(f));MAKE_FLOAT(f, 1, 128, 7 << 20);printf("%f %s\n", f, ftoa(f));printf("%s ", ltoa(0));printf("%s ", ltoa(123450));printf("%s\n", ltoa(-67890));printf("%s ", ltoa(2147483647));printf("%s ", ltoa(-2147483647));printf("%s\n", ltoa(-2147483647 - 1));return 0;
}
程序运行结果:
然后再移植到BA45F5650单片机上运行。
【strconv.h】
#define FTOA_PRECISION 8
#define FTOA_PRECISION_MAX 1e8
typedef uint32_t ftoa_fixnum_t;#define FLOAT_SIGN_HEXVAL(hexval) (((hexval) >> 23) & 1) // 1bit
#define FLOAT_CLEARSIGN_HEXVAL(hexval) ((hexval) & 0x7fffff)
#define FLOAT_EXPONENT_HEXVAL(hexval) ((((hexval) >> 15) & 0xff) - 127) // 8bits
#define FLOAT_MANTISSA_HEXVAL(hexval) ((hexval) & 0x7fff) // 15bits
#define MAKE_FLOAT_HEXVAL(s, e, m) ((((uint32_t)(s) & 1) << 23) | (((uint32_t)((e) + 127) & 0xff) << 15) | ((uint32_t)(m) & 0x7fff))
#define MAKE_FLOAT(f, s, e, m) \do { \uint32_t temp = MAKE_FLOAT_HEXVAL((s), (e), (m)); \memcpy(&(f), &temp, sizeof(f)); \} while (0)#define DTOA_PRECISION 8
#define DTOA_PRECISION_MAX 1e8
typedef uint32_t dtoa_fixnum_t;#define DOUBLE_SIGN_HEXVAL(hexval) ((hexval) >> 31) // 1bit
#define DOUBLE_CLEARSIGN_HEXVAL(hexval) ((hexval) & 0x7fffffff)
#define DOUBLE_EXPONENT_HEXVAL(hexval) ((((hexval) >> 23) & 0xff) - 127) // 8bits
#define DOUBLE_MANTISSA_HEXVAL(hexval) ((hexval) & 0x7fffff) // 23bits
#define MAKE_DOUBLE_HEXVAL(s, e, m) ((((uint32_t)(s) & 1) << 31) | (((uint32_t)((e) + 127) & 0xff) << 23) | ((uint32_t)(m) & 0x7fffff))
#define MAKE_DOUBLE(d, s, e, m) \do { \uint32_t temp = MAKE_DOUBLE_HEXVAL((s), (e), (m)); \memcpy(&(d), &temp, sizeof(d)); \} while (0)char *ftoa(float value);
char *dtoa(double value);
char *ltoa(long value);
char *hexstr(uint32_t value, uint8_t width);
【strconv.c】
#include <stdint.h>
#include <string.h>
#include "strconv.h"static const float float_table[31] = {1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f, 1.0e11f, 1.0e12f, 1.0e13f, 1.0e14f, 1.0e15f, 1.0e16f, 1.0e17f, 1.0e18f, 1.0e19f, 1.0e20f, 1.0e21f, 1.0e22f, 1.0e23f, 1.0e24f, 1.0e25f, 1.0e26f, 1.0e27f, 1.0e28f, 1.0e29f, 1.0e30f, 1.0e31f
};
static const float float_table_2[1] = {1.0e32f};
static const double double_table[31] = {1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25, 1.0e26, 1.0e27, 1.0e28, 1.0e29, 1.0e30, 1.0e31
};
static const double double_table_2[1] = {1.0e32};
static char strconv_str[50];char *ftoa(float value)
{char *p = strconv_str;float num;ftoa_fixnum_t fixnum;int16_t e, k, a, b, i;uint8_t negative;uint32_t num_hexval, value_hexval;memcpy(&value_hexval, &value, sizeof(value_hexval));negative = FLOAT_SIGN_HEXVAL(value_hexval);e = FLOAT_EXPONENT_HEXVAL(value_hexval);if (e == -127){if (!negative)strcpy(strconv_str, "0");elsestrcpy(strconv_str, "-0");return strconv_str;}else if (e == 128){if (FLOAT_MANTISSA_HEXVAL(value_hexval) == 0){if (!negative)strcpy(strconv_str, "inf");elsestrcpy(strconv_str, "-inf");}else{if (!negative)strcpy(strconv_str, "nan");elsestrcpy(strconv_str, "-nan");}return strconv_str;}e = ((int32_t)e * 19728) / 65536;k = -(FTOA_PRECISION - (e + 1));num_hexval = FLOAT_CLEARSIGN_HEXVAL(value_hexval);memcpy(&num, &num_hexval, sizeof(num));if (k > 0){a = k / 32;b = k % 32;if (a != 0)num /= float_table_2[a - 1];if (b != 0)num /= float_table[b - 1];}else if (k < 0){a = (-k) / 32;b = (-k) % 32;if (a != 0)num *= float_table_2[a - 1];if (b != 0)num *= float_table[b - 1];}num += 0.5f;if (num >= FTOA_PRECISION_MAX){e++;k++;num /= 10;}memcpy(&num_hexval, &num, sizeof(num_hexval));fixnum = FLOAT_MANTISSA_HEXVAL(num_hexval) | (1ul << 15);i = FLOAT_EXPONENT_HEXVAL(num_hexval) - 15;if (i > 0)fixnum <<= i; else if (i < 0)fixnum >>= -i;if (negative)*p++ = '-';if (e + 1 < 1){*p++ = '0';*p++ = '.';while (e + 1 < 0){*p++ = '0';e++;}i = FTOA_PRECISION;}else if (e + 1 < FTOA_PRECISION)i = FTOA_PRECISION + 1;elsei = e + 1;p[i--] = '\0';while (i >= 0){if (i >= FTOA_PRECISION && e + 1 >= FTOA_PRECISION)p[i--] = '0';else{if (i == e + 1 && i != 0)p[i--] = '.';p[i--] = '0' + fixnum % 10;fixnum /= 10;}}if (e + 1 < FTOA_PRECISION){i = FTOA_PRECISION;if (p[i] == '\0')i--;while (i >= 0 && p[i] == '0'){p[i] = '\0';i--;}if (i >= 0 && p[i] == '.')p[i] = '\0';}return strconv_str;
}char *dtoa(double value)
{char *p = strconv_str;double num;dtoa_fixnum_t fixnum;int16_t e, k, a, b, i;uint8_t negative;uint32_t num_hexval, value_hexval;memcpy(&value_hexval, &value, sizeof(value_hexval));negative = DOUBLE_SIGN_HEXVAL(value_hexval);e = DOUBLE_EXPONENT_HEXVAL(value_hexval);if (e == -127){if (!negative)strcpy(strconv_str, "0");elsestrcpy(strconv_str, "-0");return strconv_str;}else if (e == 128){if (DOUBLE_MANTISSA_HEXVAL(value_hexval) == 0){if (!negative)strcpy(strconv_str, "inf");elsestrcpy(strconv_str, "-inf");}else{if (!negative)strcpy(strconv_str, "nan");elsestrcpy(strconv_str, "-nan");}return strconv_str;}e = ((int32_t)e * 19728) / 65536;k = -(DTOA_PRECISION - (e + 1));num_hexval = DOUBLE_CLEARSIGN_HEXVAL(value_hexval);memcpy(&num, &num_hexval, sizeof(num));if (k > 0){a = k / 32;b = k % 32;if (a != 0)num /= double_table_2[a - 1];if (b != 0)num /= double_table[b - 1];}else if (k < 0){a = (-k) / 32;b = (-k) % 32;if (a != 0)num *= double_table_2[a - 1];if (b != 0)num *= double_table[b - 1];}num += 0.5;if (num >= DTOA_PRECISION_MAX){e++;k++;num /= 10;}memcpy(&num_hexval, &num, sizeof(num_hexval));fixnum = DOUBLE_MANTISSA_HEXVAL(num_hexval) | (1ul << 23);i = DOUBLE_EXPONENT_HEXVAL(num_hexval) - 23;if (i > 0)fixnum <<= i; else if (i < 0)fixnum >>= -i;if (negative)*p++ = '-';if (e + 1 < 1){*p++ = '0';*p++ = '.';while (e + 1 < 0){*p++ = '0';e++;}i = DTOA_PRECISION;}else if (e + 1 < DTOA_PRECISION)i = DTOA_PRECISION + 1;elsei = e + 1;p[i--] = '\0';while (i >= 0){if (i >= DTOA_PRECISION && e + 1 >= DTOA_PRECISION)p[i--] = '0';else{if (i == e + 1 && i != 0)p[i--] = '.';p[i--] = '0' + fixnum % 10;fixnum /= 10;}}if (e + 1 < DTOA_PRECISION){i = DTOA_PRECISION;if (p[i] == '\0')i--;while (i >= 0 && p[i] == '0'){p[i] = '\0';i--;}if (i >= 0 && p[i] == '.')p[i] = '\0';}return strconv_str;
}char *ltoa(long value)
{char temp;uint8_t i, n, start = 0;if (value == 0){strconv_str[0] = '0';strconv_str[1] = '\0';}else{if (value < 0){strconv_str[0] = '-';start = 1;}elsevalue = -value;for (i = start; value != 0; i++){strconv_str[i] = '0' + (-(value % 10));value /= 10;}strconv_str[i] = '\0';n = i - start;for (i = 0; i < n / 2; i++){temp = strconv_str[start + i];strconv_str[start + i] = strconv_str[start + n - i - 1];strconv_str[start + n - i - 1] = temp;}}return strconv_str;
}char *hexstr(uint32_t value, uint8_t width)
{char ch;uint8_t i, j = 2;uint8_t ignore = 1;strconv_str[0] = '0';strconv_str[1] = 'x';for (i = 0; i < 8; i++){ch = (value >> 28) & 0xff;value <<= 4;if (ignore && ch == 0 && 8 - i > width){continue;}ignore = 0;if (ch >= 0 && ch <= 9){ch += '0';}else if (ch >= 10 && ch <= 15){ch += 'a' - 10;}strconv_str[j] = ch;j++;}strconv_str[j] = '\0';return strconv_str;
}
【uart.h】
void dump_data(const void *data, int len);
void uart_init();
void uart_send(uint8_t data);
void uart_send_char(char ch);
void uart_send_string(const char *s);
void uart_wait_tx();
【uart.c】
#include <stdint.h>
#include <BA45F5650.h>
#include "uart.h"void dump_data(const void *data, int len)
{const char *list = "0123456789ABCDEF";const uint8_t *p = data;while (len--){uart_send_char(list[*p >> 4]);uart_send_char(list[*p & 15]);p++;}uart_send_char('\n');
}void uart_init()
{// select PA6 as UART_RX_pas15 = 1;_pas14 = 1;_ifs11 = 1;_ifs10 = 0;_papu6 = 1; // pull-up// select PA3 as UART_TX_pas07 = 1;_pas06 = 0;// change HICR frequency from 2MHz to 8MHz_hirc1 = 1;_hirc0 = 0;while (!_hircf);// set baudrate to 38400// 2MHz/(16*(12+1))->9615.385// 8MHz/(16*(12+1))->38461.538_brgh = 1;_brg = 12;// enable UART_uarten = 1;_rxen = 1;_txen = 1;
}void uart_send(uint8_t data)
{while (!_txif);_txr_rxr = data;
}void uart_send_char(char ch)
{if (ch == '\n')uart_send('\r');uart_send(ch);
}void uart_send_string(const char *s)
{while (*s)uart_send_char(*s++);
}void uart_wait_tx()
{while (!_tidle);
}
【main.c】
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#include <BA45F5650.h>
#include "strconv.h"
#include "uart.h"static void test_float()
{float value;uart_send_string(ftoa(1.245f));uart_send_string(" ");uart_send_string(ftoa(-9.36f));uart_send_string(" ");uart_send_string(ftoa(1.78f));uart_send_string(" ");uart_send_string(ftoa(1456.0f));uart_send_string(" ");uart_send_string(ftoa(0.00075f));uart_send_string(" ");uart_send_string(ftoa(0.0000491f));uart_send_string("\n");uart_send_string(ftoa(2.57e14f));uart_send_string(" ");uart_send_string(ftoa(9.46e37f));uart_send_string("\n");uart_send_string(ftoa(0.0f));uart_send_string(" ");uart_send_string(ftoa(-0.0f));uart_send_string(" ");MAKE_FLOAT(value, 0, -127, 0);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 1, -127, 0);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 0, -127, 7ul << 12);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 1, -127, 7ul << 12);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 0, 128, 0);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 1, 128, 0);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 0, 128, 7ul << 12);uart_send_string(ftoa(value));uart_send_string(" ");MAKE_FLOAT(value, 1, 128, 7ul << 12);uart_send_string(ftoa(value));uart_send_string("\n");
}static void test_double()
{double value;uart_send_string(dtoa(1.245));uart_send_string(" ");uart_send_string(dtoa(-9.36));uart_send_string(" ");uart_send_string(dtoa(1234567.0));uart_send_string(" ");uart_send_string(dtoa(1048576.0));uart_send_string(" ");uart_send_string(dtoa(-0.0000125));uart_send_string(" ");uart_send_string(dtoa(-0.000379));uart_send_string("\n");uart_send_string(dtoa(3.1415926e17));uart_send_string(" ");uart_send_string(dtoa(1.42857e38));uart_send_string("\n");uart_send_string(dtoa(0.0));uart_send_string(" ");uart_send_string(dtoa(-0.0));uart_send_string(" ");MAKE_DOUBLE(value, 0, -127, 0);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 1, -127, 0);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 0, -127, 7ul << 20);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 1, -127, 7ul << 20);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 0, 128, 0);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 1, 128, 0);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 0, 128, 7ul << 20);uart_send_string(dtoa(value));uart_send_string(" ");MAKE_DOUBLE(value, 1, 128, 7ul << 20);uart_send_string(dtoa(value));uart_send_string("\n");
}void system_reset()
{// write an incorrect value to _wdtc to reset the system_wdtc = 0;
}void main()
{uint8_t ch;uart_init();uart_send_string("BA45F5650 UART\n");uart_send_string("sizeof(float)=");uart_send_string(ltoa(sizeof(float)));uart_send_string(", ");uart_send_string("sizeof(double)=");uart_send_string(ltoa(sizeof(double)));uart_send_string("\n");test_float();test_double();while (1){// the watchdog is enabled by default and cannot be disabled by software// therefore, the watchdog timer must be cleared periodically_clrwdt(); // this also clears _to and _pdf bit// receive from UARTif (_rxif){ch = _txr_rxr;if (isprint(ch)){uart_send_string("UART character: ");uart_send(ch);uart_send_string("\n");switch (ch){case 'G':// Green LED controlif (_pcc0) // Is the pin in input mode?{// set led pin to output mode_pcc0 = 0;_pc0 = 0;}else{// led on/off_pc0 = ~_pc0;}break;case 'R':// Red LED controlif (_pcc4){_pcc4 = 0;_pc4 = 0;}else_pc4 = ~_pc4;break;case 'r':uart_send_string("RESET\n");uart_wait_tx();system_reset();break;case 'W':// Warning LED controlif (_pbc1){_pbc1 = 0;_pb1 = 0;}else _pb1 = ~_pb1;break;case 'w':uart_send_string("LVRF=");uart_send_string(ltoa(_lvrf)); // low voltage reset flaguart_send_string(", WRF=");uart_send_string(ltoa(_wrf)); // flag of software reset triggered by incorrectly writing _wdtcuart_send_string(", TO=");uart_send_string(ltoa(_to)); // watchdog reset flag (read-only)uart_send_string(", PDF=");uart_send_string(ltoa(_pdf)); // halt flag (read-only)uart_send_string("\n");// the following two bits can be cleared only by software_lvrf = 0;_wrf = 0;break;}}else{uart_send_string("UART data: ");uart_send_string(hexstr(ch, 2));uart_send_string("\n");}}}
}