IAP15W4K61S4单片机EEPROM读写程序

/*-------------关闭IAP----------------*/
              void IapIdle()
              {
              IAP_CONTR = 0;                     //关闭IAP功能
              IAP_CMD = 0;                       //清除命令寄存器
              IAP_TRIG = 0;                      //清除触发寄存器
              IAP_ADDRH = 0x80;                  //将地址设置到非IAP区域
              IAP_ADDRL = 0;
              }
/*-----从ISP/IAP/EEPROM区域读取一字节-----*/
              BYTE IapReadByte(WORD addr)
              {
              BYTE dat;                          //数据缓冲区
              IAP_CONTR = ENABLE_IAP;            //使能IAP
              IAP_CMD = CMD_READ;                //设置IAP命令
              IAP_ADDRL = addr;                  //设置IAP低地址
              IAP_ADDRH = addr >> 8;             //设置IAP高地址
              IAP_TRIG = 0x5a;                   //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                   //写触发命令(0xa5)
              _nop_();                           //等待ISP/IAP/EEPROM操作完成
              dat = IAP_DATA;                    //读ISP/IAP/EEPROM数据
              IapIdle();                         //关闭IAP功能
              return dat;                        //返回
              }
/*------写一字节数据到ISP/IAP/EEPROM区域--------*/
              void IapProgramByte(WORD addr, BYTE dat)
              {
              IAP_CONTR = ENABLE_IAP;         //使能IAP
              IAP_CMD = CMD_PROGRAM;          //设置IAP命令
              IAP_ADDRL = addr;               //设置IAP低地址
              IAP_ADDRH = addr >> 8;          //设置IAP高地址
              IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
               IAP_TRIG = 0x5a;                //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                //写触发命令(0xa5)
              _nop_();                        //等待ISP/IAP/EEPROM操作完成
              IapIdle();
              }
/*---------扇区擦除-----------*/
              void IapEraseSector(WORD addr)
              {
              IAP_CONTR = ENABLE_IAP;         //使能IAP
              IAP_CMD = CMD_ERASE;            //设置IAP命令
              IAP_ADDRL = addr;               //设置IAP低地址
              IAP_ADDRH = addr >> 8;          //设置IAP高地址
              IAP_TRIG = 0x5a;                //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                //写触发命令(0xa5)
              _nop_();                        //等待ISP/IAP/EEPROM操作完成
              IapIdle();
              }
/*************写参数到EEPROM*******************************/
              void Write_EEprom()
              {
               IapEraseSector(IAP_ADDRESS); //扇区擦除
               IapProgramByte(IAP_ADDRESS+1,val1>>8&0XFF);/*A轴速度高八位*/    
               IapProgramByte(IAP_ADDRESS+2,val1&0x00FF); /*A轴速度低八位*/
                                
               IapProgramByte(IAP_ADDRESS+3,val2>>8&0XFF);/*B轴速度高八位*/  
               IapProgramByte(IAP_ADDRESS+4,val2&0x00FF); /*B轴速度低八位*/
                                
               IapProgramByte(IAP_ADDRESS+5,val3>>8&0XFF);/*C轴速度高八位*/  
               IapProgramByte(IAP_ADDRESS+6,val3&0x00FF); /*C轴速度低八位*/

               IapProgramByte(IAP_ADDRESS+7,val4>>8&0XFF);/*D轴速度高八位*/  
               IapProgramByte(IAP_ADDRESS+8,val4&0x00FF); /*D轴速度低八位*/
                                
               IapProgramByte(IAP_ADDRESS+9,val5>>8&0XFF);/*润滑模数高八位*/  
               IapProgramByte(IAP_ADDRESS+10,val5&0x00FF);/*润滑模数低八位*/

               IapProgramByte(IAP_ADDRESS+11,val6>>8&0XFF);/*润滑时间高八位*/  
               IapProgramByte(IAP_ADDRESS+12,val6&0x00FF); /*润滑时间低八位*/

               IapProgramByte(IAP_ADDRESS+13,val7>>8&0XFF);/*吹气时间1高八位*/  
               IapProgramByte(IAP_ADDRESS+14,val7&0x00FF); /*吹气时间1低八位*/
                                
               IapProgramByte(IAP_ADDRESS+15,val8>>8&0XFF);/*吹气时间2高八位*/  
               IapProgramByte(IAP_ADDRESS+16,val8&0x00FF); /*吹气时间2低八位*/

               IapProgramByte(IAP_ADDRESS+17,val9>>8&0XFF);/*打油次数高八位*/  
               IapProgramByte(IAP_ADDRESS+18,val9&0x00FF); /*打油次数低八位*/

               IapProgramByte(IAP_ADDRESS+19,val10>>8&0XFF);/*间隙时间高八位*/  
               IapProgramByte(IAP_ADDRESS+20,val10&0x00FF); /*间隙时间低八位*/

               IapProgramByte(IAP_ADDRESS+21,val11>>8&0XFF);/*攻丝超时高八位*/  
               IapProgramByte(IAP_ADDRESS+22,val11&0x00FF); /*攻丝超时低八位*/

               IapProgramByte(IAP_ADDRESS+23,val12>>8&0XFF);/*旋转超时高八位*/  
               IapProgramByte(IAP_ADDRESS+24,val12&0x00FF); /*旋转超时低八位*/

               IapProgramByte(IAP_ADDRESS+25,val13>>8&0XFF);/*退刀超时高八位*/  
               IapProgramByte(IAP_ADDRESS+26,val13&0x00FF); /*退刀超时低八位*/

               IapProgramByte(IAP_ADDRESS+27,val14>>8&0XFF);/*润滑超时高八位*/  
               IapProgramByte(IAP_ADDRESS+28,val14&0x00FF); /*润滑超时低八位*/
               //val15
               IapProgramByte(IAP_ADDRESS+29,val15>>8&0XFF);/*过桥开时间高八位*/  
               IapProgramByte(IAP_ADDRESS+30,val15&0x00FF); /*过桥开时间低八位*/

               IapProgramByte(IAP_ADDRESS+31,val16>>8&0XFF);/*手动速度高八位*/  
               IapProgramByte(IAP_ADDRESS+32,val16&0x00FF); /*手动速度低八位*/
              }
/***********************************/
              void red_eeprom(void)
              {
              uint m,n;        
              m=IapReadByte(IAP_ADDRESS+1);           //A轴速度高八位
              n=IapReadByte(IAP_ADDRESS+2);           //A轴速度低八位
              val1=(m*256+n)&0X7FFF;                  //A轴速度屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+3);           //B轴速度高八位
              n=IapReadByte(IAP_ADDRESS+4);           //B轴速度低八位
              val2=(m*256+n)&0X7FFF;                  //B轴速度屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+5);           //C轴速度高八位
               n=IapReadByte(IAP_ADDRESS+6);           //C轴速度低八位
              val3=(m*256+n)&0X7FFF;                  //C轴速度屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+7);           //调整时间高八位
              n=IapReadByte(IAP_ADDRESS+8);           //调整时间低八位
              val4=(m*256+n)&0X7FFF;                  //调整时间屏蔽最高负位 111 1111    
              m=IapReadByte(IAP_ADDRESS+9);           //润滑模数高八位
              n=IapReadByte(IAP_ADDRESS+10);          //润滑模数低八位
              val5=(m*256+n)&0X7FFF;                  //润滑模数屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+11);          //润滑时间高八位
              n=IapReadByte(IAP_ADDRESS+12);          //润滑时间低八位
              val6=(m*256+n)&0X7FFF;                  //润滑时间屏蔽最高负位 111 1111    
              m=IapReadByte(IAP_ADDRESS+13);          //吹气时间1高八位
              n=IapReadByte(IAP_ADDRESS+14);          //吹气时间1低八位
              val7=(m*256+n)&0X7FFF;                  //吹气时间1屏蔽最高负位 111 1111    
              m=IapReadByte(IAP_ADDRESS+15);          //吹气时间2高八位
              n=IapReadByte(IAP_ADDRESS+16);          //吹气时间2低八位
              val8=(m*256+n)&0X7FFF;                  //吹气时间2屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+17);          //打油次数高八位
              n=IapReadByte(IAP_ADDRESS+18);          //打油次数低八位
              val9=(m*256+n)&0X7FFF;                  //打油次数屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+19);          //间隙时间高八位
              n=IapReadByte(IAP_ADDRESS+20);          //间隙时间低八位
              val10=(m*256+n)&0X7FFF;                  //间隙时间屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+21);          //攻丝超时高八位
              n=IapReadByte(IAP_ADDRESS+22);          //攻丝超时低八位
              val11=(m*256+n)&0X7FFF;                  //攻丝超时屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+23);          //攻丝超时高八位
              n=IapReadByte(IAP_ADDRESS+24);          //旋转超时低八位
              val12=(m*256+n)&0X7FFF;                  //旋转超时屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+25);          //退刀超时高八位
              n=IapReadByte(IAP_ADDRESS+26);          //退刀超时低八位
              val13=(m*256+n)&0X7FFF;                  //退刀超时屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+27);          //润滑超时高八位
              n=IapReadByte(IAP_ADDRESS+28);          //润滑超时低八位
              val14=(m*256+n)&0X7FFF;                  //润滑超时屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+29);          //过桥开时间高八位
              n=IapReadByte(IAP_ADDRESS+30);          //过桥开时间低八位
              val15=(m*256+n)&0X7FFF;                  //过桥开时间屏蔽最高负位 111 1111
              m=IapReadByte(IAP_ADDRESS+31);          //手动速度高八位
              n=IapReadByte(IAP_ADDRESS+32);          //手动速度低八位
              val16=(m*256+n)&0X7FFF;                  //手动速度屏蔽最高负位 111 1111
              }    
/*************恢复出厂值************/
              void RESET_Data()    
              {
              val1=10;                                  //电机速度
              val2=18000;                              //退丝补偿
              val3=2;                                  //补偿速度
              val4=10;                                  //调整时间
              val5=100;                                  //润滑模数
              val6=20;                                  //润滑时间
              val7=1;                                  //吹气时间1
              val8=1;                                  //吹气时间2
              val9=10;                                  //缺料计时
              val10=2;                                  //间隙时间
              val11=10;                                  //攻丝超时
              val12=10;                                  //旋转超时
              val13=25;                                  //退刀超时
              val14=25;                                  //润滑超时
              val15=5;                                  //过桥开时间
              val16=1;                                  //手动电机速度
              }
/***********************************/
              void Dis_Data(void)
              {
               printf("n0.val=%d\xff\xff\xff",val1);  //电机速度
               printf("n0.val=%d\xff\xff\xff",val1);  //退丝补偿
               printf("n1.val=%d\xff\xff\xff",val2);  //补偿速度
               printf("n2.val=%d\xff\xff\xff",val3);  //C轴速度
               printf("n3.val=%d\xff\xff\xff",val4);  //D轴速度    
               printf("n4.val=%d\xff\xff\xff",val5);  //润滑模数
               printf("n5.val=%d\xff\xff\xff",val6);  //润滑时间
               printf("n6.val=%d\xff\xff\xff",val7);  //吹气时间1
               printf("n7.val=%d\xff\xff\xff",val8);  //吹气时间2
               printf("n9.val=%d\xff\xff\xff",val9);  //打油次数
               printf("n10.val=%d\xff\xff\xff",val10);//间隙时间
               printf("n11.val=%d\xff\xff\xff",val11);//攻丝超时
               printf("n12.val=%d\xff\xff\xff",val12);//旋转超时
               printf("n13.val=%d\xff\xff\xff",val13);//退刀超时
               printf("n14.val=%d\xff\xff\xff",val14);//润滑超时
              }                
/****************刷新显示*******************/                            
              void Renovate(void)
              {
               uint mn;
               mn=0X00;
               printf("n0.val=%d\xff\xff\xff",mn);      //A轴速度
               printf("n0.val=%d\xff\xff\xff",mn);    //A轴速度
               printf("n1.val=%d\xff\xff\xff",mn);      //B轴速度
               printf("n2.val=%d\xff\xff\xff",mn);    //C轴速度    
               printf("n3.val=%d\xff\xff\xff",mn);      //D轴速度    
               printf("n4.val=%d\xff\xff\xff",mn);    //润滑模数
               printf("n5.val=%d\xff\xff\xff",mn);      //润滑时间
               printf("n6.val=%d\xff\xff\xff",mn);    //吹气时间1
               printf("n7.val=%d\xff\xff\xff",mn);      //吹气时间2
               printf("n9.val=%d\xff\xff\xff",mn);    //打油次数    
               printf("n10.val=%d\xff\xff\xff",mn);      //间隙时间
               printf("n11.val=%d\xff\xff\xff",mn);   //攻丝超时
               printf("n12.val=%d\xff\xff\xff",mn);      //旋转超时
               printf("n13.val=%d\xff\xff\xff",mn);   //退刀超时
               printf("n14.val=%d\xff\xff\xff",mn);      //润滑超时
               red_eeprom();
               Dis_Data();
              }        
/******************************************************/                            
              void Data_Set(void )
              {
               if (a[0]==0XD5&&a[1]==0X00)       //A轴速度
               {
               val1=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X01)  //B轴速度
               {
               val2=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X02)  //C轴速度
               {
               val3=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X03)  //D轴速度
               {
               val4=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X04)  //比例系数1
               {
               val5=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X05)  //比例系数2
               {
               val6=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if (a[0]==0XD5&&a[1]==0X06)  //吹气时间1
               {
               val7=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X07)   //吹气时间2
               {
               val8=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X08)   //打油次数
               {
               val9=a[3]*256+a[2];               //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X09)   //打油计数器
               {
               val10=a[3]*256+a[2];              //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X0A)   //攻丝超时
               {
               val11=a[3]*256+a[2];              //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X0B)   //旋转超时
               {
               val12=a[3]*256+a[2];              //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X0C)   //退刀超时
               {
               val13=a[3]*256+a[2];              //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
               else if(a[0]==0XD5&&a[1]==0X0D)   //润滑超时
               {
               val14=a[3]*256+a[2];              //
               Write_EEprom();
               Renovate();                       //刷新显示
               }
              }  

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前言: 记得在上大二下的时候参加了2015全国电子设计大赛,题目刚下来便决定了做C题"多旋翼的自主飞行器"4天3夜拿到瑞萨最小系统后便开始写各个模块的驱动代码,因为有开发环境CUBE的神助攻,所以前期的驱动代码是还很顺利的。接下来便是飞行器的组装和电路板 制作,在一起就绪后花掉了2天时间,剩下的两天便疯狂调试,最苦恼的是电池供给跟不上,无奈只能调调停停,初次制作算法也还不够成熟,我直接用的以前做平衡车的经验。不过最后飞得也还算平稳,用的手机加蓝牙控制飞行(后来想一想也是胆大),但题目要求自主飞行,于是我便苦恼了,我便开始记录四旋翼起飞的油门,在起飞后直接给油门(危险)效果也还可以,就在比赛前一天晚上出事故了 一块刚充满电的电池 我装上做最后测试。电池电量过高 直接结果导致飞机飞太高撞到了天花板,结果将飞机撞坏了一个电机,桨就不用说了 惨,不过幸运的是人没事。队友也傻了,怎么办?此时已是凌晨1点。我们捡起“残骸”拍拍上面的灰,听了首“安河桥”便开始和队友一起埋头苦干。哈哈···最后在早上6点前飞机修好了 虽然效果大打折扣不过最基本的任务还算能够完成。第二天比赛,我们是下午开始。第一次参赛,试飞的时候发现异常,冷静后发现超声波线松了 排除故障后开始比赛,比赛结果就不往下写了。(。。。。。)无论怎样我很享受这个过程。比赛结束后便有了做一个小四轴的想法,于是便在网上搜索资料,偶然看到了STC的这个开源项目,于是便自己也动手做了一个,控制代码我也有重写,现分享给大家!!!一起交流!!! 功能概述: 本设计是基于STC15W4K61S4的微型四轴。以STC15W4K61S4为主控。硬件包括,mpu6050传感器,电源,nrf2401通信模块,720空心杯电机,PCB机架。姿态解算采用四元数,串级PID作为控制器,配合遥控器实现俯仰,横滚,偏航姿态控制。主要用于学习和理解四轴飞行器的基本原理。 实物图: 应用场景: 控制思路: 首先调整电机1,3同向 2,4同向 且相邻电机旋转反相在X型模式下首先通过mpu6050获取三轴加速度计和三轴陀螺仪数据 经过数据处理融合后 得到姿态角度pitch roll 以及Z轴陀螺仪积分出 yaw角。将得到的姿态角送入PID控制器计算输出对应的油门补偿对应的电机 从而使四旋翼平衡。简单来说飞机往那边沉 对应的电机就加速提高升力抵抗它下沉,它的下沉程度是通过角度来反映的而已,具体补偿多少合适,则是通过PID控制器计算的而已。单纯通过角度误差来控制,是属于单级的PID 控制。经过试验这种控制策略应用在小四轴效果不太理想,因此我们通常采用的串级PID控制小四轴,即引入了角速度环,通常内环使用PD(对象角速度)外环使用PI(对象角度&内环输出)这样的控制策略在测试中效果较好,但理想的参数调整比较难,因此需要耐心调试才能得到较好的效果。 系统框图: 本系统硬件设计组成: 主控:STC15W4K61S4 (封装:LQFP32) 传感器:MPU6050(三轴加速度计,三轴陀螺仪)(封装:QFN)https://www.datasheet5.com/pn-MPU-6050-1083104 电机:720空心杯 MOS管 AO3400A (封装:SOT23_M)https://www.datasheet5.com/pn-AO3400A-1215185 2.4G无线:NRF2401 (模块)https://www.datasheet5.com/datasheet/NRF2401/250319... 电源芯片: ME6219 (封装:SOT95)https://www.bom2buy.com/search/ME6219 BL8530-501SM(封装:SOT89)https://www.datasheet5.com/pdf/BL8532/1751621/BELLI... 元器件成本估算: 部分器件成本估算:https://www.bom2buy.com/list/1312-stc15w4k61s4 总结: 此项目在大三上完成,经过调试 能够实现基本飞行,同时也存在以下问题: 参数应该还不够理想(遥控器跟随效果不好)。 PCB设计过大 导致超重,因为担心手焊的MPU不好使故留了较多直插模块接口同时还考虑到十字和X型所以各留了一个这样的直插接口。 这是一次不错的动手经历吧,从原理图PCB到代码都是自己一个人完成,每当遇到问题就网上寻求答案,过程还是很坎坷的,不过也特别有意思。同时也学到很多知识,做事情也更加细心严谨! 测试结果: 手机里翻了半天总算找到了一点视频上传与大家分享,效果不太好希望勿喷。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值