矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 4104|回复: 16

求索之四 尝试使用单片机

[复制链接]
     
发表于 2018-2-12 08:13:41 | 显示全部楼层 |阅读模式
年前有时间手欠进了片STC15F260S2,配上原来手头有的0.96寸OLED(IIC接口)就开始玩起。目前玩到浮点数。

其他不说,先上效果,过程明天楼下见:
0.jpg
     
 楼主| 发表于 2018-2-12 10:07:23 | 显示全部楼层
商家提供的例程结构不错,稍加修改就可以整合。

先解决显示问题,直接使用0.96OLED工程,接好工程中指定的信号结编译、写入,正常显示后,再改时钟和数据脚,一切正常后做改造。

例程功能还是蛮全的:显示字符、数值、字符串、中文、图片。

我的目标与例程差距大些:开辟显示缓冲区,以显点、清点为基础去实现所有显示操作。为什么这样做?一方面练手,二方面好解决统一刷新显示。

1.128x64计1024字节,初始化按行排列,共7页。
2.构造OLED_SetDot(x,y)函数,难点在定位(x,y)是哪字节哪位。当时人品暴发,一次写成,现在源码不在手头,过后贴上。
3.从SETDOT构造OLED_ClrDot(x,y)函数。
4.用CLRDOT构造清屏函数。
5.用SetDot构造OLED_Char(x,y,c)函数。原函数有些草:左上角占只能在某字节的b0位,新构造的函数没有要求。
6.再构造Str、Num、LNum、Hex函数。因还没用到中文,所以中文字函数没做,要做也是简单。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 10:23:32 | 显示全部楼层
再解决'心跳'问题。我对代码没什么经验,但知道如Uninx、M$、RTos等都有时钟,感觉中我这个片子应该也要有统一的心跳:定时中断,1ms一次,中断中记下启动后经历的ms数,顺便记100ms、秒、分、时、天。

一切正常后构造时间显示函数,再构造显示缓冲区向显示器传数据更新显示。细节:设置同步变量,一但这个变量为1,就在定时中断中经历N个心跳后调用传送缓冲区数据。为了方便主动传送,定时中断中固定N心跳调用传送,在传送函数中去判断缓冲区是否是'脏'的,干净不脏则没有必要耗时间传送。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 10:32:36 | 显示全部楼层
尝试ADC,同OLED、定时一样,用商家提供的例程,只要丢弃原例程中的main函数,把原文件当作模块,现#include进工程即可。

ADC用中断方式,P1的8口全用上,每次中断都把原始的值记进相应的adc变量中。然后在主函数中把测得的数据显示出来。

不难。
回复 支持 反对

使用道具 举报

     
发表于 2018-2-12 10:47:39 | 显示全部楼层
照片太小,看不清楚。介绍太专业,还看不明白。是如何将代码写进STC15F230S2的?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 11:39:32 | 显示全部楼层
hujj 发表于 2018-2-12 10:47
照片太小,看不清楚。介绍太专业,还看不明白。是如何将代码写进STC15F230S2的?


别说'太专业',会吓人的。我也是业余玩玩。

村里面摆大桌,工作间余发帖子,先行说个大概,有空再贴上代码。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 12:23:43 | 显示全部楼层
本帖最后由 longker 于 2018-2-12 13:35 编辑

ADC基准加入。

应用中电压稳定性方面薄弱,而ADC基准是用供电电压,直接使用ADC结果误差肯定大,若是用高精度供电会引入复杂性,人家的做法是:供个相对稳定的电压作参考电压,用一路先测该电压后马上测目标电压,再通过计算得出相对准确的目标电压。

参考电压用431供,电路简单,元器件好找,老主板上有431。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 13:20:13 | 显示全部楼层
C51上浮点数运算不难,要显示就有些麻烦。

度娘是找到的机理:
1.浮点数4字节存储。
2.格式SEEE_EEEE EMMM_MMMM MMMM_MMMM MMMM_MMMM
3.S,一位符号位,1为负,0为正
4.E,8位指数位
5.M,23(+1)位有效数字
6.E的处理记得再减127才是真正的结果
7.M的处理:23位M在前面添加上固定的1.代表真实的数构成24位有效值,即1.MMMMMMMMMMM...
8.1.MMMM....移小数点处理,E减127得到真实指数e后,根据这个e移动小数点,如e为+3则有效数变成1MMM.MMMMMMMMM...负数e则左移
9.小数点左边从右起第n位的加权是2^(n-1)为整数,小数点右边从左起第n位的加权是2(-n)为小数。如1.00-1.0,10.00-2.0(2+0),11.00-3.0(2+1),0.100-0.5,0.110-0.75(0.5+0.25),0.111-0.875(0.5+0.25+0.125)...

你要显示,麻烦多多,刚开始时想偷懒,运算时就把结果扩大10000倍想避免处理小数部分,在BCD码修正时耗费好多时间,狂汗。也许有更加好的办法,请熟手们指指路。

补充内容 (2018-2-12 16:23):
好多笔误:2^(-n)少标^
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-12 13:24:29 | 显示全部楼层
有空再去读许老师的数字LCR代码,学习他怎么处理。

好好学习天天向上
回复 支持 反对

使用道具 举报

     
发表于 2018-2-14 13:34:09 | 显示全部楼层
longker 发表于 2018-2-12 12:23
ADC基准加入。

应用中电压稳定性方面薄弱,而ADC基准是用供电电压,直接使用ADC结果误差肯定大,若是用 ...

这个片子的AD第九通道,就是片内的基准电压,不用另加431,还浪费一路AD。
回复 支持 反对

使用道具 举报

     
发表于 2018-2-14 13:36:03 | 显示全部楼层
longker 发表于 2018-2-12 13:20
C51上浮点数运算不难,要显示就有些麻烦。

度娘是找到的机理:

不用自己转换,用fprintf函数转成字符串显示。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-14 23:44:24 | 显示全部楼层
本帖最后由 longker 于 2018-2-14 23:47 编辑
zhxzhx 发表于 2018-2-14 13:34
这个片子的AD第九通道,就是片内的基准电压,不用另加431,还浪费一路AD。


谢谢提示,有空去认真读手册。

也顺便回下楼:因是业余水平,真的不知道还能这样处理。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-2-14 23:45:53 | 显示全部楼层
zhxzhx 发表于 2018-2-14 13:34
这个片子的AD第九通道,就是片内的基准电压,不用另加431,还浪费一路AD。

忘记问了:第9通道手册中有提到不?应该怎么用?
回复 支持 反对

使用道具 举报

     
发表于 2018-2-17 12:06:26 | 显示全部楼层
本帖最后由 zhxzhx 于 2018-2-17 12:18 编辑
longker 发表于 2018-2-14 23:45
忘记问了:第9通道手册中有提到不?应该怎么用?


在手册的1.18节,后面还有一个部分,在10.7节
void ShowResult(uchar ch)
{
    uint adc_res10,//测量设定通道adc值
    bandgap,       //bandgap预储存校准值,单位毫伏
    adc_9gallery_res; //测量第九通道(bandgap)值
    float power_voltage,        //系统供电电压,单位毫伏
    ADC_voltage;     //设定通道电压值,单位毫伏
   
    uchar  code *cptr; //定义ROM(代码)区指针
    //uchar  idata *iptr;//定义RAM(内存)区指针
   
    cptr = ID_ADDR_ROM;         //从程序区读取BandGap电压值(单位:毫伏mV)
    bandgap=*cptr++;
    bandgap<<=8;
    bandgap+=*cptr;
    /*iptr = ID_ADDR_RAM;         //从内存区读取BandGap电压值(单位:毫伏mV),貌似不推荐
    bandgap=*iptr++;              //两种方法结果一样,
                        //上面的方法需要在下载式勾选"在ID号前添加重要测试参数"选项,才可在程序中获取此参数
    bandgap<<=8;                  //下面的这种方法不需要
    bandgap+=*iptr;    */
    //测量设定通道adc值
    ADC_RES = 0;                    //清除结果寄存器
    P1ASF = 0xff;                   //设置P1口为AD口
    GetADCResult(ch);                //GetADCResult(ch)函数是从adc处读结果,输入时通道号,P1.0口就是0通道,以此类推
    GetADCResult(ch);                 //读三次获得稳定
    adc_res10= GetADCResult(ch);
    //测量第九通道(bandgap)值
    ADC_RES = 0;                    //清除结果寄存器
    P1ASF = 0x00;                   //设置读第九通道
    GetADCResult(0);                 //测bandgap时,调用此函数时通道数只能填0
    GetADCResult(0);                 //读三次获得稳定
    adc_9gallery_res=GetADCResult(0);
    //计算系统供电电压
    power_voltage=(float)bandgap*1024/adc_9gallery_res;
    //计算ADC通道测得电压值
    ADC_voltage=(float)bandgap*adc_res10/adc_9gallery_res;
    printf("P1.%d ADC result:%d\n",(uint)ch,adc_res10);
    printf("BandGap standard:%d mV\n",bandgap);
    printf("BandGap value:%d \n",adc_9gallery_res);
    printf("system power voltage:%.0f mV\n",power_voltage);
    printf("ADC voltage:%.0f mV\n",ADC_voltage);
}
回复 支持 反对

使用道具 举报

     
发表于 2018-2-19 00:37:54 | 显示全部楼层
手里没有屏,到目前为止只会玩1602。便宜
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-5-2 03:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表