数码之家

 找回密码
 立即注册
搜索
查看: 1956|回复: 15

[C51] 有没有人能把stc15w408as t12移植到stc8h3k64s2

[复制链接]
发表于 2023-5-5 17:48:44 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
stc15w408as adc用法不一样,stc8h3k64s2不支持p1asf语句,按照示例胡乱复制一通t12控制板灯一直亮温度不受控,由于是tssop20的stc8h3k64s2数码管管脚不够用,接了tm1650数码管模块4位结果不亮,stc15w408as能点亮,下面给出改的程序看看哪里有问题

#include "STC8H.H"
#include "INTRINS.h"//头文件
// 定义一个数码管段码表,0~F
unsigned char CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0X39, 0X5E, 0X79, 0X71};


unsigned int code wendubiao[62]={924,959,996,1033,1071,1110,1150,1190,1232,1273,1315,1358,1401,1443,1487,1501,1574,1619,1663,1706,1751,1756,1776,1810,1853,1903,1958,2017,2078,2141,2204,2266,2327,2387,2444,2500,2554,2607,2657,2706,2738,2800,2844,2889,2931,2974,3016,3056,3098,3139,3179,3218,3257,3296,3333,3372,3408,3446,3484,3519,3554,3590};//根据NTC电阻随温度变化进而引起电压变化得出的数据,用来查表计算室温(进而对热电偶冷端补偿)
sbit t12=P3^6;//T12通过P2.0控制
sbit encoderb=P3^4;//编码器的b脚接P1.4
sbit encodera=P3^2;//编码器的a脚接P3.2
sbit bianmaanniu=P3^3;//编码器的按键接P3.3
sbit DIO = P3 ^ 7;         // TM1650 数码管驱动的sda引脚
sbit CLK = P3 ^ 5;   
bit e=1,f=1;//e,f用来保存编码器上一次的状态
bit huancunkaiguan=0;//用于改变设定温度后延时显示设定温度(而不是立刻显示t12温度)
signed int huancun;//显示函数直接显示huancun,要显示一个数据将必须这个数据赋值给缓存(由于数码管只有三位,为了在显示三位数同时保持四位数的精度,所以实际显示的是数据除以10,支持显示负数)
signed int shiwen;//10倍实际室温,即实际室温乘以10(为了精确)(允许的室温范围为-11度至50度)
signed int t12wendu;//T12烙铁头的实际温度(非热电偶的温差)(同样为10倍温度)
signed int shedingwendu;//设定温度(范围200~450度)
signed int wencha;//T12两个周期间的温差
signed int jiareshu;//每200ms加热周期内需要加热的次数(一次等于1ms,相当于加热占空比)
unsigned char zhouqijishu;//加热周期200ms计数
unsigned int huancunjishu;//用于改变设定温度后保持显示设定温度一段时间再显示t12温度(而不是立刻显示t12温度)
unsigned long cankaodianya0,t12dianya,ntcdianya,dianyuandianya;


void delay_ms (unsigned int a)//24MHz时钟时的1毫秒延时函数
{
unsigned int b;
while(a--)
{
  for(b=0;b<1200;b++);
}
}




/********************************10us延时函数************************************************/


void delay_10us (unsigned int a)//24MHz时钟时的10微秒延时函数
{
unsigned int b;
while(a--)
{
  for(b=0;b<12;b++);
}
}
/********************************数码管延时关断函数******************************************/
void initADC(void)
        {P1M0 = 0x00;                                //设置P1.0为ADC口
    P1M1 = 0x07;
    P_SW2 |= 0x80;
    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;
    ADCCFG = 0x0f;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x80;                           //使能ADC模块


    while (1)       
                        {
        ADC_CONTR |= 0x40;                      //启动AD转换
        _nop_();
        _nop_();
        while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
        ADC_CONTR &= ~0x20;                     //清完成标志
        P2 = ADC_RES;                           //读取ADC结果
    }
                        }
/********************************ADC公共函数**************************************************/
void gonggonghanshu2(void)//此函数测量单片机电源电压
{
ADC_CONTR=0x88;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0
delay_10us(5);//延时等待转换结束
ADC_RESL=ADC_RESL&0x03;//取转换结果低八位中的低二位
cankaodianya0=(ADC_RES*4+ADC_RESL);//把结果转换成十进制数据(10位ADC,最大值1023)
dianyuandianya=2549760/cankaodianya0;//计算电源电压,单位mV
}


/********************************ADC测电压函数************************************************/
void adc (void)//ADC函数,用于测量和计算各种电压
{
signed char a;//查NTC表用
signed int b;//两次温度求平均值用
gonggonghanshu2();//公共函数2(此函数功能是测量电源电压,单位mV)


ADC_CONTR=0x89;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0 转换采用最低速度速,低速更精确(测量t12电压务必使用最低速度AD转换,实测高速误差大)
delay_10us(5);
ADC_RESL=ADC_RESL&0x03;
t12dianya=(ADC_RES*4+ADC_RESL);
t12dianya=2490*t12dianya/cankaodianya0;//计算t12电压,单位mV   
       
ADC_CONTR=0x8a;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0   
delay_10us(5);
ADC_RESL=ADC_RESL&0x03;
ntcdianya=(ADC_RES*4+ADC_RESL);
ntcdianya=2490*ntcdianya/cankaodianya0;//计算ntc电压,单位mV
ntcdianya=dianyuandianya-ntcdianya;       
       
for(a=0;wendubiao[a]<ntcdianya;a++)//查表计算室
  {
   if(a>=61)//如果超出表的范围就取允许的最高温度(50度)
   break;//并且退出查表
  }
shiwen=(a-11)*10;//得出室温(实际室温乘以10)
t12wendu=t12dianya*40*10/263+shiwen-130;//计算t12的实际温度,其中260为运放增益
if((t12wendu-b)>-2000&&(t12wendu-b)<2000)//如果两次温度相差不超过200度
  t12wendu=(t12wendu+b)/2;//就两次温度求平均值
if(t12wendu<shiwen)//如果t12温度小于室温
  t12wendu=shiwen;//就取室温
b=t12wendu;//记录上一次温度
if(t12wendu>5000)//如果得出的温度超过500度,说明没有插入烙铁头或参数错误(因为烙铁头的温度不可能超过500度)
  t12wendu=5000;//显示500作为错误指示(注意显示函数显示的是1/10,所以要显示500,需要赋值5000)
if(huancunkaiguan==1)//如果缓存开关开,说明刚刚改变了设定温度
  huancun=shedingwendu;//于是显示设定温度(而不是t12温度)
else
  huancun=t12wendu;//否则直接显示t12温度
}


/********************************定时器0初始化函数*******************************************/
void timer0init (void)//定时器0初始化程序,24MHz频率下,每1ms中断一次
{
TMOD=0x00;//定时模式,16位自动重装
TH0=0xf8; //计时1ms
TL0=0x2f;
ET0=1;//开启定时器0中断
TR0=1;//启动定时器0
}


/********************************以下是TM1650数码管显示相关的函数****************************************************/


void Start1650(void)
{ //开始信号
  CLK = 1;
  DIO = 1;
  delay_10us(5);
  DIO = 0;
  delay_10us(5);
  DIO = 0;
}


void Ask1650(void)
{ //ACK信号
  unsigned char timeout = 1;
  CLK = 1;
  delay_10us(5);
  CLK = 0;
  while ((DIO) && (timeout <= 100))
  {
    timeout++;
  }
  delay_10us(5);
  CLK = 0;
}


void Stop1650(void)
{ //停止信号
  CLK = 1;
  DIO = 0;
  delay_10us(5);
  DIO = 1;
  delay_10us(5);
}


void WrByte1650(unsigned char oneByte)
{ //写一个字节,高位在前,低位在后
  unsigned char i;
  CLK = 0;
  delay_10us(1);
  for (i = 0; i < 8; i++)
  {
    oneByte = oneByte << 1;
    DIO = CY;
    CLK = 0;
    delay_10us(5);
    CLK = 1;
    delay_10us(5);
    CLK = 0;
  }
}
/*
unsigned char Scan_Key(void)
{ // 按键扫描
  unsigned char i;
  unsigned char rekey;
  Start1650();
  WrByte1650(0x49); //读按键命令
  Ask1650();
  //DIO = 1;
  for (i = 0; i < 8; i++)
  {
    CLK = 1;
    rekey = rekey << 1;
    if (DIO)
    {
      rekey++;
    }
    Delay_us(5);
    CLK = 0;
  }
  Ask1650();
  Stop1650();
  return (rekey);
}
*/


void Set1650(unsigned char add, unsigned char dat)
{ //数码管显示
  //写显存必须从高地址开始写
  Start1650();
  WrByte1650(add); //第一个显存地址
  Ask1650();
  WrByte1650(dat);
  Ask1650();
  Stop1650();
}


// 初始化1650,传入亮度参数,范围0~7
void init1650(unsigned char light)
{
  Set1650(0x48, ((light << 4) | 0x01));
}


// 数码管显示函数
void display(signed int num)
{
  // 计算这个数字对应的千百十个位的数字
  unsigned int tmpnum, qian, bai, shi, ge;
  if (num < 0)
    num = -num;
  tmpnum = num;
  qian = tmpnum / 1000;
  tmpnum %= 1000;
  bai = tmpnum / 100;
  tmpnum %= 100;
  shi = tmpnum / 10;
  ge = tmpnum % 10;


  Set1650(0x68, CODE[qian]);
  Set1650(0x6A, CODE[bai]);
  Set1650(0x6C, CODE[shi]);
  Set1650(0x6E, CODE[ge]);
}


/********************************公共函数6(记录编码器状态)**********************************/
void gonggonghanshu6(void)
{
e=encodera;//记录编码器a脚此次状态
f=encoderb;//记录编码器b脚此次状态
}


/********************************编码器函数(正常加热模式调用)********************************/
void bianmaqi(void)
{
if(e==1&&f==1&&encodera==1&&encoderb==0)//和前一次状态比较确定为右旋
  {
   shedingwendu=shedingwendu+100;//步进
   if(shedingwendu>4500)//最高允许450度
    shedingwendu=4500;
   huancun=shedingwendu;//显示改变后的设定温度
   huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
   huancunjishu=0;//重新开始缓存计数
  }
if(e==1&&f==1&&encodera==0&&encoderb==1)//和前一次状态比较确定为左旋
  {
   shedingwendu=shedingwendu-100;//步进
   if(shedingwendu<2000)//最低允许200度
    shedingwendu=2000;
   huancun=shedingwendu;//显示改变后的设定温度
   huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
   huancunjishu=0;//重新开始缓存计数
  }
gonggonghanshu6();//记录编码器状态
}


/********************************定时器0中断函数********************************************/
void timer0(void) interrupt 1//定时0中断函数,用于检测旋转编码器,掉电存储等操作
{
unsigned char buchang;
bianmaqi();//调用编码器函数
if(huancunkaiguan==1)//延时显示计数
  huancunjishu++;
zhouqijishu++;//加热周期计数
if(jiareshu>190)//最多加热190ms
  jiareshu=190;
if(zhouqijishu<=jiareshu)//如果当前计数小于等于加热数
  t12=1;//就加热
else//否则
  t12=0;//不加热
if(t12wendu==5000)//如果t12温度为500,说明没有插入烙铁头或参数严重错误
  t12=0;//停止加热
if(huancunjishu==1500)//设定温度延时显示1.5秒
  {
   huancunkaiguan=0;//如果达到了1.5秒,关闭缓存开关
   huancunjishu=0;//停止缓存计数
   huancun=t12wendu;//由显示设定温度改为显示t12温度
  }
if(zhouqijishu==200)//t12停止加热后10ms再检测温度
  {
   adc();//检测电压,计算温度
   zhouqijishu=0;//重新开始加热周期计数    //////////////////////////以下为加热算法(请自行理解,不作注释)//////////////////////
   if(t12wendu>shedingwendu)
    {
     if(t12wendu-shedingwendu<=20)
      jiareshu=(shedingwendu-1500)/160;
     else
      jiareshu=0;
    }
   if(t12wendu<=shedingwendu)
    {
     wencha=shedingwendu-t12wendu;
     if(wencha>20)
      {
       buchang++;
       if(buchang>150)
        buchang=150;
      }
     else
      buchang=0;
     if(shedingwendu-t12wendu>=300)
      jiareshu=190;
     else if(shedingwendu-t12wendu>=200)
      jiareshu=160;
     else if(shedingwendu-t12wendu>=150)
      jiareshu=130;
     else if(shedingwendu-t12wendu>=100)
      jiareshu=90+wencha/2+buchang;
     else if(shedingwendu-t12wendu>=50)
      jiareshu=50+buchang*2;
     else
      jiareshu=(shedingwendu-1000)/80+wencha*2/3+buchang;
    }
   }
}


/********************************主函数*****************************************************/
void main (void)//主函数
{
P1M0=0x00;//P1除P1.0,P1.1,P1.2为输入模式外均为正常模式
P1M1=0x07;
P2M0 = 0x01;
P2M1 = 0xfe;
P3M0 = 0xe0;
P3M1 = 0x1c;
initADC();
init1650(1); // 初始化TM1650显示
shedingwendu=2800;//设为300度
IE=0x88;//打开定时器0中断,关闭定时器1中断
timer0init();//初始化定时器0
   
                        while(1)
{
  display(huancun);//数码管显示数据
}
        }

头像被屏蔽
发表于 2023-5-6 09:11:24 | 显示全部楼层
可以直接参考STC工程师写好的范例:

KVP~3S]YEZWDLZ%BJM`DO)E.png
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2023-5-6 09:15:19 | 显示全部楼层
楼主也可以试下:STC8H3K64S2-45I-LQFP32,12位ADC,管脚也够用,不需要扩容。
回复 支持 反对

使用道具 举报

发表于 2023-5-6 13:26:59 | 显示全部楼层
疯狂的兔子来了 发表于 2023-5-6 09:11
可以直接参考STC工程师写好的范例:

太6了我之前都没发现示例程序
回复 支持 反对

使用道具 举报

发表于 2023-5-6 15:21:32 | 显示全部楼层


STC8H配套的库函数,RTOS都很完整
image.png
回复 支持 反对

使用道具 举报

发表于 2023-5-13 11:15:18 | 显示全部楼层
楼主搞定了吗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-13 19:36:08 | 显示全部楼层

没有搞定,adc用法不一样,自己零基础,也就15w408as t12会简单胡乱改改,想用来模仿模拟白光控制方式固定加热时间,不加热时一直检测温度低了继续加热,15w408as精度灵敏度还是差了些,adc回差不够小十位应该只能精确到1度,闪灯不够细腻
回复 支持 反对

使用道具 举报

发表于 2023-5-13 23:08:31 | 显示全部楼层
                        while(1)
{
  display(huancun);//数码管显示数据
}

先把这句改成   display(1234);
看看显示能不能亮
回复 支持 1 反对 0

使用道具 举报

发表于 2023-5-13 23:09:45 | 显示全部楼层
我一般会先调通显示,然后把显示输出作为调试手段,看程序到底运行到哪里了
回复 支持 反对

使用道具 举报

发表于 2023-5-13 23:11:42 | 显示全部楼层
看看是不是管脚的输出需要初始化,好像新版的默认上电是低电平,老版的上电是高电平
回复 支持 反对

使用道具 举报

发表于 2023-5-18 23:38:11 | 显示全部楼层
楼主加油,最近我也是打算做数码管T12,计划用STC8H8K64U这款芯片,正在从零学51单片机 ,共同进步
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2023-5-19 09:01:38 | 显示全部楼层
STC8H8K64U可以直接USB下载和仿真,核心板的范例,直接下载应用!
image.png
回复 支持 反对

使用道具 举报

发表于 2023-5-26 20:40:37 | 显示全部楼层
楼主原理图来一下,谢谢
回复 支持 反对

使用道具 举报

发表于 2023-7-14 11:34:24 | 显示全部楼层
目前确实用stc8h的芯片才是最好的选择,支持楼主研究。
回复 支持 反对

使用道具 举报

发表于 2024-5-13 16:04:27 | 显示全部楼层
参考下范文,还是不清楚。
回复 支持 反对

使用道具 举报

发表于 2024-5-14 00:05:11 | 显示全部楼层
改别人的还不如自己写个,能读懂别人写了啥,基本自己也能写出来了
直接上显示屏,用啥数码管
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-6-2 17:09 , Processed in 0.218401 second(s), 9 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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