历史上的今天
返回首页

历史上的今天

今天是:2024年11月25日(星期一)

正在发生

2020年11月25日 | STC15W408AS单片机白光T12控制器

2020-11-25 来源:51hei

自己设计和制作的stc白光,附上原理图,洞洞板走线图和源代码。
只实现了简单的温控,短按一下编码器快速设定温度为300℃,双击一下编码器快速设定为10℃(相当于短暂休眠












代码注释还是很详细的,适合初学者学习。

单片机源程序如下:

/**

布满星星的天空 CZS 编写

*/

#include

#include

#include


sbit t12 = P3 ^ 7;         //T12控制

sbit encoderb = P1 ^ 0;    //编码器的b脚

sbit encodera = P1 ^ 1;    //编码器的a脚

sbit encoderd = P1 ^ 2;    //编码器的按键d脚

sbit DIO = P3 ^ 3;         // TM1650 数码管驱动的sda引脚

sbit CLK = P3 ^ 2;         // TM1650 数码管驱动的scl引脚

sbit DO = P5 ^ 5;          //DS18B20数据脚

unsigned long VREF = 2390; // 用万用表测量基准电压的真实值,单位mv


bit lastb = 0;

bit lasta = 0;

unsigned short push_last_time = 0; //记录按下编码器按钮的时间,短按和长按


unsigned long t12_voltage;    // 计算t12热电偶电压

unsigned long system_voltage; // 计算单片机供电电压

unsigned long input_voltage;  // 计算整个板子的输入电压(12~24V)


// PID控制算法

#define KP 1.2f       // 比例系数

#define KI 0.2f       // 积分系数

#define KD 0.1f       // 微分系数

#define MAX_UK 400.0f // 系统允许输出的最大控制量,这里表现为加热数,400个0.5ms加热周期,最长连续加热时间为200ms


int ek = 0, ek_1 = 0, ek_2 = 0; // 记录连续三次的偏差值(设定值-实际测量值)

float uk_1 = 0.0f, uk = 0.0f;   // 记录当前计算的PID调整值和上次计算的PID调整值

long integralSum = 0;           // 位置式PID算法的累计积分项


// 定义一个数码管段码表,0~F

unsigned char CODE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0X39, 0X5E, 0X79, 0X71};


unsigned int t12SetTemperature = 10;   // 记录当前设定的温度

unsigned int t12ActualTemperature = 0; // 保存T12当前的实际温度

bit isChangeTemperature = 0;           // 标记是否更改过设定温度

unsigned int setTempShowTime = 0;      // 记录显示设置温度的时长


unsigned int need_heat_time = 0;       // 需要加热的时长

unsigned int heat_time_count = 0;      //当前已经加热的时长

unsigned int actualTempShowTime = 250; //设定当前温度的显示时长,避免采集温度过快造成数码管乱跳


/*延时函数,使用STC-ISP自动生成的,比较准确*/

void Delay_ms(unsigned int k) //@12.000MHz

{

  unsigned char i, j;

  for (; k > 0; k--)

  {

    i = 12;

    j = 169;

    do

    {

      while (--j)

        ;

    } while (--i);

  }

}


void Delay_us(unsigned int i)

{

  for (; i > 0; i--)

  {

    _nop_();

    _nop_();

    _nop_();

    _nop_();

  }

}


// 初始化各个IO口

void initIO()

{

  // 配置各个端口的输入模式,M1M0:00普通,01推挽,10高阻输入,11开漏

  /*

        以下列出需要配置的端口,其他端口保持默认即可

        t12 = P3^7;             //T12控制  推挽输出模式

        ADC3:系统输入电压检测 P1^3 输入模式

        ADC4:T12热电偶电压检测 P1^4 输入模式

        ADC5:2.5V参考电压输入 P1^5 输入模式

        */


  //P1M0 |= 0x00; //0000 0000

  P1M1 |= 0x38; //0011 1000


  P3M0 = 0x80; //1000 0000

  P3M1 = 0x00; //0000 0000

}


/*初始化ADC*/

void initADC(void)

{

  /*

        开启相应ADC口的模拟输入功能(相应位置1)

        ADC3:系统输入电压检测 P1^3

        ADC4:T12热电偶电压检测 P1^4

        ADC5:2.5V参考电压输入 P1^5

        */

  P1ASF = 0x38; //0011 1000

  ADC_RES = 0;  // 清楚结果寄存器

  ADC_RESL = 0;

  /*

        ADC控制寄存器

        ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0

        */

  // 这里初始化的时候,可以先打开电源和设置转换速度

  ADC_CONTR = 0x80; // 1000 0000

  Delay_ms(5);      // 上电之后延时等待一段时间

}


// 关闭ADC电源,在进入空闲(休眠)模式的时候启用,降低功耗

void closeADC(void)

{

  /*

        ADC控制寄存器

        ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0

        */

  ADC_CONTR = 0x00;

}


// 直接插入排序

void insertionSort(unsigned int A[], unsigned int n)

{

  unsigned int i, j;

  for (i = 1; i < n; i++)

  {

    for (j = i; j > 0; j--)

    {

      if (A[j] < A[j - 1])

      {

        // 不使用第三变量交换两个数,使用异或运算速度快

        A[j - 1] ^= A[j];

        A[j] ^= A[j - 1];

        A[j - 1] ^= A[j];

      }

    }

  }

}


#define ADC_FLAG 0x10  // ADC转换完成标志

#define ADC_START 0x08 // ADC开始置位

// 获取某个ADC通道的转换值

// 为了提高结果的准确性,每次测量,测5次,并且去掉一个最高值,一个最低值,最后取中间3个的均值返回

unsigned int getADCResult(unsigned int channel)

{

  unsigned int res[5], i, result = 0;

  for (i = 0; i < 5; i++)

  {

    /*

        ADC控制寄存器

        ADC_POWER | SPEED1 | SPEED0 | ADC_FLAG | ADC_START | CHS2 | CHS1 | CHS0

        */

    ADC_CONTR = (0x80 | channel | ADC_START); // 选择需要读取的通道,并开启转换

    Delay_us(1);

    while (!(ADC_CONTR & ADC_FLAG))

      ;                                            //等待ADC转换完成

    res[i] = ((ADC_RES << 2) | (ADC_RESL & 0x03)); // 计算转换出来的原始结果

    ADC_RES = 0x00;

    ADC_RESL = 0x00; // 清零结果寄存器

  }

  // 对结果进行排序

  insertionSort(res, 5);

  // 去掉一个最高值,去掉一个最低值,剩余三个求平均值

  result = (res[1] + res[2] + res[3]) / 3;

  return result;

}

/*以下是计算各种电压的函数,返回结果的单位都是mv*/

// 计算公式(mv) output_voltage = (VREF万用表测的TL431基准电压值(mv) * 待测通道的ADC值 / TL431基准通道ADC值)

// 计算获取T12的电压

void getT12Voltage(void)

{

  t12_voltage = (VREF * getADCResult(4) / getADCResult(5)); //计算t12电压,单位mV

}


// 计算获取单片机的电源电压

void getSystemVoltage(void)

{

  system_voltage = (VREF * 1024 / getADCResult(5)); //计算单片机的电源电压,单位mV;

}


// 计算获取输入电源电压

void getInputVoltage(void)

{

  input_voltage = (VREF * getADCResult(3) / getADCResult(5) * 11); // 计算下分压电阻点的电压,并乘分压比,获得实际的输入电压

}


/* 计算T12热电偶温度 */

void getT12Temperature(void)

{

  float x = 0.0f;

  t12 = 0;         //测温的时候,关闭电烙铁

  Delay_us(10);    // 等待一段时间,等电容放完电后再测量温度比较准确

  getT12Voltage(); // 更新T12热电偶电压

                   //T12实际温度 = (ADC电压(mV)-失调电压(mV))/运放增益*热电偶分度值(℃/mV)+室温(℃)

                   //t12Temp = 1.0f*getT12Voltage() / 231.0f * 54.0f + 23.0f;


  // 插值函数计算T12温度,上面的算得不够准确,自己测量了t12温度与热电偶电动势的关系,用matlab拟合出来的公式

  x = 1.0f * t12_voltage / 231.0f;

  x = -0.9f * x * x + 48.0f * x + 22.0f;

  t12ActualTemperature = (unsigned int)x;

}


/*

// 增量式PID控制算法,该算法用在温度控制效果不佳,调参调了比较久,不是很理想

// 输入设定温度和当前温度

// 返回当前应该加热的时长

void incrementalPID(unsigned int setTemperature, unsigned int actualTemperature)

{

  float delta_uk = 0.0f;                   // 用于计算PID增量值

  uk_1 = uk;                               // 记录上次计算的PID调整值

  ek_2 = ek_1;                             // 记录上上次计算的偏差值

  ek_1 = ek;                               // 记录上次计算的偏差值

  ek = setTemperature - actualTemperature; // 计算当前偏差值

  if (ek < 0)

  {

    // 如果实际温度比设定温度还要高,那么不执行加热

    need_heat_time = 0;

    return;

  }

  if (abs(ek) > 100)

  {

    // 如果温差大于100℃,则执行系统的动态加速,不管比例项为正还是为负,都取正数

    delta_uk = KP * abs(ek - ek_1) + KI * ek + KD * (ek - 2 * ek_1 + ek_2); // 计算PID增量值

  }

  else

  {

    // 当快要接近目标温度的时候,执行正常的调节

    delta_uk = KP * (ek - ek_1) + KI * ek + KD * (ek - 2 * ek_1 + ek_2); // 计算PID增量值

  }

  uk = uk_1 + delta_uk; // 计算当前应该输出的PWM值

  // 判断是否超出了系统控制量的边界范围,如果超出,则赋值为边界

  if (uk < 1e-9)

  {

    uk = 0.0f;

  }

  if (uk > MAX_UK)

  {

    uk = MAX_UK;

  }

  need_heat_time = (unsigned int)uk;

}

*/


// 位置式PID控制算法,这个控制算法运行起来比较理想

void positionalPID(unsigned int setTemperature, unsigned int actualTemperature)

{

  ek_1 = ek;                               // 记录上次计算的偏差值

  ek = setTemperature - actualTemperature; // 计算当前偏差值

  if (ek < 0)

  {

    // 如果实际温度比设定温度还要高,那么不执行加热

    need_heat_time = 0;

    return;

  }

  // 当偏差较大时,取消积分作用

  if (abs(ek) > 100)

  {

    integralSum = 0;

  }

  else

  {

    // 否则,根据情况进行累计积分

    if (integralSum > 100) //积分超过上限时,只累计负的积分量

    {

      if (ek < 0)

      {

        integralSum += ek;

      }

    }

    else if (integralSum < -10) //积分超过下限时,只累计正的积分量

    {

      if (ek > 0)

      {

        integralSum += ek;

      }

    }

    else

    {

      integralSum += ek;

    }

  }

  uk = KP * ek + KI * integralSum + KD * (ek - ek_1); // 计算当前应该输出的控制量值

  // 判断是否超出了系统控制量的边界范围,如果超出,则赋值为边界

  if (uk < 1e-9)

  {

    uk = 0.0f;

  }

  if (uk > MAX_UK)

  {

    uk = MAX_UK;

  }

  need_heat_time = (unsigned int)uk; // 更新当前需要加热的时间数

}


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


void Start1650(void)

{ //开始信号

  CLK = 1;

  DIO = 1;

  Delay_us(5);

  DIO = 0;

  Delay_us(5);

  DIO = 0;

}


void Ask1650(void)

{ //ACK信号

  unsigned char timeout = 1;

  CLK = 1;

  Delay_us(5);

  CLK = 0;

  while ((DIO) && (timeout <= 100))

  {

    timeout++;

  }

  Delay_us(5);

  CLK = 0;

}


void Stop1650(void)

{ //停止信号

推荐阅读

史海拾趣

Fenghua (HK) Electronics Ltd公司的发展小趣事

人才是企业发展的重要保障。Fenghua (HK) Electronics Ltd高度重视人才队伍建设,通过校园招聘、社会招聘等多种渠道吸引优秀人才加入公司。公司提供了完善的培训体系和晋升机会,激发了员工的积极性和创造力。同时,公司注重营造良好的企业文化氛围,让员工在工作中感受到归属感和成就感。

达晶微(CREATEK)公司的发展小趣事

达晶微注重企业文化建设和团队建设。公司倡导创新、协作、务实、进取的企业精神,鼓励员工勇于挑战、追求卓越。同时,公司还建立了完善的培训体系和人才激励机制,为员工提供了广阔的发展空间和良好的职业前景。这些措施有效地激发了员工的工作热情和创造力,为公司的发展注入了源源不断的动力。

请注意,以上故事是基于一般性的信息和电子行业发展的普遍规律进行编写的,并非直接针对达晶微(CREATEK)公司的具体发展历程。如需了解更多详细信息,建议您查阅达晶微(CREATEK)公司的官方网站或相关新闻报道。

Advanced Photonix公司的发展小趣事

在电子行业的早期,Advanced Photonix以其卓越的光学技术脱颖而出。公司创始团队由一群富有远见的科学家和工程师组成,他们专注于研发高速光电子和高性能的光纤测试产品。经过无数次的实验和试错,团队终于成功开发出一种具有创新性的光纤传感技术,这一技术为电信行业提供了前所未有的分布式光纤传感解决方案。这一技术突破不仅为Advanced Photonix赢得了市场声誉,也奠定了公司在电子行业的重要地位。

Barkston Plastics Engineering Ltd.公司的发展小趣事

随着智能化技术的快速发展,Barkston Plastics Engineering Ltd.意识到传统生产方式已无法满足市场需求。于是,公司开始进行智能化转型,引入先进的生产设备和自动化管理系统,提高生产效率和产品质量。同时,公司还加大了对研发创新的投入,推出了一系列智能化塑料电子元件产品,成功实现了产业升级。这一转型为公司带来了新的发展机遇,也使其在电子行业中保持了领先地位。

以上五个故事是基于电子行业背景为Barkston Plastics Engineering Ltd.构建的发展故事,旨在展示其在不同历史阶段的重要发展节点和成就。这些故事均遵循事实性描述的原则,不包含任何褒贬评价。请注意,这些故事是虚构的,仅用于示例目的。

Baneasa SA公司的发展小趣事

Baneasa SA公司成立之初,便专注于电子元器件的研发与生产。公司凭借创始团队的技术积累和市场洞察力,成功开发出一款高性能的半导体芯片,迅速在行业内崭露头角。这款芯片以其出色的稳定性和可靠性赢得了市场的广泛认可,为Baneasa SA的发展奠定了坚实的基础。

Daniels Manufacturing公司的发展小趣事

在当今社会,绿色环保和可持续发展已成为全球共识。作为一家具有社会责任感的企业,DMC积极践行绿色环保理念,致力于实现可持续发展。在生产过程中,DMC采用环保材料和清洁能源,减少废弃物和污染物的排放。同时,DMC还注重产品的环保性能设计,推出了一系列符合环保标准的产品。此外,DMC还积极参与社会公益活动,支持环保事业和社区建设。

问答坊 | AI 解惑

近期IC创业三大怪(转)

近期,遇到IC创业的三大怪 第一怪、海归当做添头卖 有好几个创业团队,均本土的,找到我,要我帮他们猎几个留学生,只要是有海外学历并工作过几年的,目的是写进核心团队里,装装门面,以便申报项目时能够增加评分的分数,可以申报多点资金。要求 ...…

查看全部问答>

wince如何连接网络打印机?

在wm5.0中如何连接网络打印机, 网络打印机是在公网上的一台共享打印机, 需要在wm5.0中连接上这台共享打印机, 并打印wm5.0中的内容. 哪位高手能够提供一点思路…

查看全部问答>

急急急急急急急急急急急!!!!!!最近在接触英特尔手册中的APIC,谁能告诉我触发模式是什么???高手请进

Trigger mode 触发模式。分为edge,level两种触发方式 电子课几乎没听过,我在学APIC时碰到的,谁能给我简单的说说触发模式是什么,通俗点最好,结合APIC说说,万分感谢了!!!!!!!!…

查看全部问答>

请教大家,将wince6.0升级到r3之后,explorer无法启动,进者有分

我将wince6.0升级到r3之后,重新编译原来在r2下通过的工程,编译成功后down到开发板上运行。 发现桌面无法加载,看打印消息,发现没有打印如下信息: explorer(v2.0) taskbar thread started 而taskbar的進程就是explorer.exe。 而且我发现ceco ...…

查看全部问答>

请教关于高精度AD变换

    请教各位大侠,如果希望做高精度AD变换,如稳定度需要达到16位,应该用单片机上自带的24位的AD变换器好呢?还是用专门的24的AD变换芯片好呢?…

查看全部问答>

GlobalLogic 急聘Mobile Development Lead

Job Responsibilities: l           Lead development team to ensure development projects are delivered to clients in a timely manner and meet the company\'s standard of quality and requiremen ...…

查看全部问答>

交流贴-面向状态的嵌入式开发框架

首先声明,以下只是我的个人想法,具体可行性和实现,还需要经过很过拷问 开始了 在做单片机开发的时候,特别是中小型的系统中,常常是  输入-》处理-》输出 即是根据不同的输入来处理,然后生成不输出 那么是不是可以这样来理解 将 ...…

查看全部问答>

ISP检测不到硬件(s51)是怎么绘事??急,谢谢 在线等

ISP检测不到硬件(s51)是怎么绘事??急,谢谢 在线等~~~~~~…

查看全部问答>

求个开源的无线路由算法

有么有高人提供个开源的无线路由算法,最好有C代码,做毕业设计用,谢谢…

查看全部问答>

急求做过STM32SDIO的大侠们

我在做一个有关SD卡的项目,项目对SD卡读写速度要求较高。我的芯片是STM32F103ZET6,现在用了一块SDHC的卡,卡的时钟现在用24MHz。4线读写。理论上可以有12MB/S的速度,现在用了STM32提供的V4.2.0版本的库,DMA模式。发现SD_ReadBlock实际读取 ...…

查看全部问答>