找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 316|回复: 4
打印 上一主题 下一主题
收起左侧

做了个开关换挡,利用P32电平来决定换挡还是读取当前

[复制链接]
跳转到指定楼层
楼主
做好了开关换挡的代码判断P32的电平来决定换挡还是不换.
现在有时灵有时又不灵. 电路图,代码如下
求大神帮下我.

  1. #include "stc8g.h"
  2. #include "intrins.h"
  3. #include "eeprom.h"
  4. #include <stdio.h>

  5. #define MAIN_Fosc 11059200UL
  6. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)
  7. //#define EEPROMId           0x0E00

  8. typedef unsigned char u8;
  9. typedef unsigned int u16;

  10. //u8 PWMData[] = {181,111,51,2};//添加数组,设置需要的档位
  11. u8 PWMData[] = {2,8,31};//添加数组,设置需要的档位
  12. u16 delayTime = 3000;//这里修改需要的工作时间,单位(ms)

  13. u8 dat;
  14. u16 EEPROMId = 0020;
  15. u16 time;
  16. sbit CAP = P3^2;
  17. u8 iscap=0;


  18. u8 mode = 0;


  19. void delayms(u16 ms);   
  20. void sys_init();
  21. void PWM_init(void);
  22. void Timer0_Init(void);

  23.   void UartInit()
  24. {
  25.     SCON = 0x5a;
  26.     TL1 = BRT;
  27.     TH1 = BRT >> 8;
  28.         TR1=1;
  29.     AUXR = 0x40;
  30. }



  31. u8 LEDControl()
  32. {       
  33.          
  34.        
  35.         u8 i;
  36.         u8 length = (sizeof(PWMData)/sizeof(PWMData[0]));
  37.                 delayms(20);

  38. //        u16 EEPROMId = 0XE00;                                //将指针指向第8扇区的第一个字节
  39. //        SetMode(CMD_READ);                                //设置为读取数据
  40.        

  41.        
  42.         while(1)
  43.         {               
  44.                
  45.                                 
  46.                 dat = IapRead(EEPROMId + 1);                        //读取下一字节数据255
  47.        
  48.           
  49.                 
  50.                 if(dat == 0XFF)                                        //下一字节字节未写入数据255
  51.                 {
  52.                        
  53.                         dat = IapRead(EEPROMId);                //读取当前字节数据
  54. //                        SetMode(CMD_PROGRAM);                        //写入数据
  55.                        
  56.                 
  57.                         
  58.                         for(i = 0; i < length-1; i++)
  59.                         {        if(dat == i)
  60.                                 {       
  61.                                         if(iscap)
  62.                                         {
  63.                                         IapProgram(EEPROMId+1,i+1);
  64.                                         }
  65.                                         return dat;
  66.                                 }
  67.                         }
  68.                
  69. //                        dat=0;
  70.                         IapProgram(EEPROMId+1,0);

  71.                         return dat;                                        //返回当前字节数据
  72.                 }
  73.                 else                                                        //下一字节不为空,指针加一,继续判断下一个字节
  74.                 {        EEPROMId++;
  75.                 }


  76.                 if(EEPROMId >= 0XFFD)                                //如果当前字节到达EEPROM末尾,擦除扇区所有数据
  77.                 {       
  78. //                        SetMode(CMD_ERASE);                        //扇区擦除
  79.                         IapErase(0x0000);                                //擦除扇区
  80.                         IapErase(0x0200);                                //擦除扇区       
  81.                         IapErase(0x0400);                                //擦除扇区       
  82.                         IapErase(0x0600);                                //擦除扇区       
  83.                         IapErase(0x0800);                                //擦除扇区       
  84.                         IapErase(0x0A00);                                //擦除扇区       
  85.                         IapErase(0x0C00);                                //擦除扇区       
  86.                         IapErase(0x0E00);                                //擦除扇区                               
  87.                         return 1;
  88.                 }
  89.         }
  90. }


  91. void main()
  92. {               
  93.        

  94.         sys_init();  

  95.               iscap=CAP;       
  96.           P3M0 = 0x04; P3M1 = 0x00;   //P32推挽输出对电容充电
  97.   LEDControl();
  98.         UartInit();
  99.   

  100.        
  101.       PWM_init();
  102.        

  103.                 CCAP1H = PWMData[dat] ;  

  104.           while(1)
  105.         {
  106.                 printf("id=%u\n",EEPROMId);
  107.                 printf("cap=%bu\n",CCAP1H);
  108.                 printf("cap=%bu\n",iscap);
  109.                 delayms(1000);

  110.        
  111.         }

  112. }



  113. void sys_init(void)
  114. {
  115.         P_SW2=0x80;

  116. //    P3M0 = 0x04; P3M1 = 0x00;      
  117.        
  118.     Timer0_Init();

  119.        
  120.         IT0=1;EX0=1;
  121.         INTCLKO|=0x40;   //EX4=1; 允许INT4外部中断
  122. //        IP2H=0x00;               
  123.         IP2=0x10;

  124.        
  125.        
  126. //         ES = 1;                //关闭串口中断,可以双击换挡
  127.         EA=1;                        //打开总中断

  128. }


  129. //// 初始化PWM功能
  130. void PWM_init(void)
  131. {
  132.     CCON = 0x00;
  133.     CMOD = 0x08;
  134.     CL = 0x00;
  135.     CH = 0x00;

  136.     CCAPM1 = 0x42;
  137.     PCA_PWM1 = 0x00;
  138.     CCAP1L = 0x00;                  
  139.     CCAP1H = 0x00;
  140.         CR=1;       
  141. }


  142. //u8 TimeNum = 1;//这里是定时器中断时间,单位(ms)

  143. void Timer0_Isr(void) interrupt 1
  144. {       
  145. //        u8 Num = delayTime/TimeNum;//中断执行多少次到达工作时间
  146. //        if(time < Num)
  147. //        {        time++;
  148. //        }else if(time == Num)        //到达要求的时间
  149. //        {        IapProgram(EEPROMId+2,dat);
  150. //                time++;
  151. //        }



  152.        
  153.        
  154. }

  155. void Timer0_Init(void)                //1毫秒@11.0592MHz
  156. {

  157.         AUXR |= 0x80;                        //定时器时钟1T模式


  158.         TMOD &= 0xF0;                        //设置定时器模式
  159.         TL0 = 0xCD;                                //设置定时初始值
  160.         TH0 = 0xD4;                                //设置定时初始值
  161.         TF0 = 0;                                //清除TF0标志
  162.         TR0 = 1;                                //定时器0开始计时
  163.         ET0 = 1;                                //使能定时器0中断
  164. }


  165. void INT4_Isr(void) interrupt 16
  166. {
  167. IAP_CONTR=0x60;                       
  168. }


  169. void INT0_Isr(void) interrupt 0
  170. {
  171. //                  printf("dat=%bu\r\n",dat);
  172. //                printf("id=%u\r\n",EEPROMId);               
  173. }

  174. void delayms(u16 ms)
  175.         {u16 i;
  176.         do{
  177.                 i = MAIN_Fosc /10000;
  178.                 while(--i);
  179.         }                while(--ms);
  180. }
  181.        
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1121801 发表于 2024-8-27 13:39 | 只看该作者
像这种时灵时不灵的问题一般都是在程序的延时问题上,延时的时候没有及时处理按键信号导致的,自己仔细查一下程序,把程序延时去掉或者单独空语句延时看一下是不是不会出现遗漏信号的情况,如果没有出现就说明延时程序与按键检测存在冲突了
回复

使用道具 举报

板凳
ID:879348 发表于 2024-8-27 14:38 | 只看该作者
我之前已经回复过,STC不适合这种断电换挡,你可以对比下面2张图,实现这个功能应广单片机和STC的差别,需要比较多外围元件,原因是STC断电以后会消耗电容,而且是非线性的,然后还有STC IO口检测电平会随着电压改变,这意味着电池电压会严重影响时间判断,所以需要LDO,至于应广的工作原理就不说了,因为又是和STC完全不同的原理

回复

使用道具 举报

地板
ID:1130333 发表于 2024-8-27 15:06 | 只看该作者
cyi8 发表于 2024-8-27 13:39
像这种时灵时不灵的问题一般都是在程序的延时问题上,延时的时候没有及时处理按键信号导致的,自己仔细查一 ...

已经改代码了. 主要是不能按字节写入
现在我是整页擦除,然后循环擦除页.
10万擦写变成 80万擦写.
算是变相延长寿命把
功能已经实现了.
回复

使用道具 举报

5#
ID:1130333 发表于 2024-8-27 15:08 | 只看该作者
wufa1986 发表于 2024-8-27 14:38
我之前已经回复过,STC不适合这种断电换挡,你可以对比下面2张图,实现这个功能应广单片机和STC的差别,需 ...

已经改代码了. 现在这个代码是按字节写入,写完整个eeprom的字节再擦除.寿命3亿次以上
现在代码是按页擦除写入. 4k = 8个扇区
10万次变80万,也足够了.

只监控P32引脚的电平. 根据电平变化决定换挡还是不换挡.
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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