切割机控制板
代码修改 单选框和双态按钮联动
beep 50
r1.val=0
bt0.val=1
bt0.txt="时间方式"
printh C0 00 00 00 00 00 FA
beep 50
r0.val=0
bt0.val=0
bt0.txt="位置方式"
printh C0 01 00 00 00 00 FA
if(bt0.val==1)
{
//此时按键是按下的
bt0.txt="时间方式"
r0.val=1
r1.val=0
printh C0 01 00 00 00 00 FA
}else
{
//此时按键是弹起的
r0.val=0
r1.val=1
bt0.txt="位置方式"
printh C0 00 00 00 00 00 FA
}
else if(a[0]==0XB0) //B0 00发送主画面 内容
{
if(a[1]==0X00) //
{
red_eeprom();
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n2.val=%d\xff\xff\xff",DELAY_B);//切割时间 校对
printf("n4.val=%d\xff\xff\xff",DELAY_C);//切割时间 校对
printf("n5.val=%d\xff\xff\xff",MODEMARK);//切割时间 校对
}
if(a[1]==0X01) //
{
if(MODE_FLAG==0)
{
FLAG_S=1; // 时间模式
printf("r0.val=%d\xff\xff\xff",FLAG_S);//
printf("bt0.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=0; // 时间模式
printf("r1.val=%d\xff\xff\xff",FLAG_S);//
}
else if(MODE_FLAG==1)
{
FLAG_S=0; // 位置模式
printf("r0.val=%d\xff\xff\xff",FLAG_S);//
printf("bt0.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=1;
printf("r1.val=%d\xff\xff\xff",FLAG_S);//
}
}
}
//发送参数到触摸屏
单片机型号
/*********焊管机切割控制程序************/
/***L667 CODE3561 2026 8 29 IAP15E413AS*/
/*********位置 启动 自动 手动***********/
/*********电机 气缸 手动 自动***********/
#include <REG52.H> // cutting 切割
#include <intrins.h> //
#include <string.h> //
#include "stdio.h" //
#define uint unsigned int //
#define uchar unsigned char //
sfr INT_CLKO=0x8F; //外部中断2 P3.6 扩展寄存器
#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP字节读命令
#define CMD_PROGRAM 2 //IAP字节编程命令
#define CMD_ERASE 3 //IAP扇区擦除命令
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0000 //时间 EEPROM首地址
typedef unsigned char BYTE; //Catch_Up接上Catch_Dwon接下
typedef unsigned int WORD;
bit Signauto=0; /*退出循环检测*/
bit Rst_Bit=0; /**/
bit MODE_FLAG; /*工作模式*/
bit AutoCut_FLAG; //自动切割
bit ManualCut_FLAG; //手动切割
bit TableBack_FLAG; //台板退到位
sbit Motor=P1^0; //电机
sbit Cutting_dwon=P1^1; //切割机下降
sbit OUTA=P1^4; //备用
sbit OUTB=P1^5; //时间,模式 位置模式 指示
sbit OUT0=P1^6; //手动循环信号指示
sbit OUT1=P1^7; //定时中断 指示
sbit OUT2=P2^7; //台板
sbit Manual=P1^2; //手动指示
sbit Automatic=P1^3; //自动指示
// sbit INTPUT0=P3^5; //气缸退
// sbit INTPUT1=P3^3; //自动P3^3
// sbit INTPUT2=P3^2; //手动P3^2
// sbit INTPUT3=P3^4; //临时切割3^4
// sbit INTPUT4=P3^5; //定长切割3^5
sbit INTPUT0=P3^2; //定长红外信号
sbit INTPUT1=P3^3; //临时切割
sbit INTPUT2=P3^4; //手动
sbit INTPUT3=P3^5; //自动
sbit INTPUT4=P3^6; //气缸退到位
uint Ad_data;
uint Run_TIME; //
uint DELAY_A,DELAY_B,DELAY_C; //切割延时
uint MODEMARK;
uint aa=0; /****RUN FLAG****/
uint a[10]; //定义数组a
uchar i; //串口接收计数器
uchar k; //信号输入高电平计数器
uint counter; //产量计数器
bit Receive_Flag; //串口接收标志
bit Run_Flag; //自动运行标志
uint FLAG_S; //触摸屏显示标志
uchar kcounter,kstatus; //按键计数标志 按键状态标志
/*----关闭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 val=IapReadByte(IAP_ADDRESS+1);
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();
}
/*------------------------------------------*/
void delay(uint t)
{
uint i,j;
for(i=0;i<t;i++)
for(j=0;j<1000;j++);
}
/*-----------(1)延时子程序12MHz 加千百十个显示--------*/
void Delay100ms(uint x) //
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<11000;j++);
}
/********************************************/
void resrt_io()
{
FLAG_S=1; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //
Motor=1; //电机关
Cutting_dwon=1; //切割机下降
OUTA=1; //
OUTB=1; //
Manual=0; //手动指示
Automatic=1; //自动指示
}
/****************按键计数器状态寄存器归零*************/
void RstKey()
{
kcounter=0; //按键计数器归零
kstatus=0; //状态寄存器归零
}
/*****************按键低电平检测函数*****************/
void LowVoltKey(void) //按键计数器状态标志加一
{
kcounter++;
kstatus++;
}
/*****************按键高电平检测函数*****************/
void HighVoltKey(void) //按键计数器加一 状态标志归零
{
kcounter++; //按键计数器加一
kstatus=0; //按键状态标志归零
}
/******************************************/
void red_eeprom(void)
{
uint m,n;
m=IapReadByte(IAP_ADDRESS); //时间前八位
n=IapReadByte(IAP_ADDRESS+1); //时间后八位
DELAY_A=m*256+n; //排气一段延时时间
m=IapReadByte(IAP_ADDRESS+2); //时间前八位
n=IapReadByte(IAP_ADDRESS+3); //时间后八位
DELAY_B=m*256+n; //排气一段延时时间
MODEMARK=IapReadByte(IAP_ADDRESS+4);//工作模式
DELAY_C=IapReadByte(IAP_ADDRESS+5);//电机启动后延时切割
}
/******************************************/
void Write_EepromTime()
{
IapEraseSector(IAP_ADDRESS); //扇区擦除
IapProgramByte(IAP_ADDRESS,DELAY_A/256); // 高位
IapProgramByte(IAP_ADDRESS+1,DELAY_A%256); // 低位
IapProgramByte(IAP_ADDRESS+2,DELAY_B/256); // 高位
IapProgramByte(IAP_ADDRESS+3,DELAY_B%256); // 低位
IapProgramByte(IAP_ADDRESS+4,MODEMARK); // 工作模式
IapProgramByte(IAP_ADDRESS+5,DELAY_C%256); // 电机启动后延时切割
}
/*****************************************/
/***产量 工作模式 自动手动 启动Run_TIME***/
void start()
{
Manual=1; //手动指示
Automatic=0; //自动指示
Run_TIME=0; //初始化
if(MODE_FLAG==1) //
{
/*一:启动无输入为1,永久循环*/
FLAG_S=2; // 位置模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
do
{ //INTPUT3 启动信号
if(ManualCut_FLAG==1) //手动临时切割标志
{
ManualCut_FLAG=0;
FLAG_S=2; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Motor=0; //电机开
Delay100ms(DELAY_C); //电机启动后延时切割
Cutting_dwon=0; //切割机下降
Delay100ms(DELAY_B);
Motor=1; //电机关
Delay100ms(10); //延时1秒
OUT2=0; //台板返回
TableBack_FLAG=1; //台板退标志
Cutting_dwon=1; //切割机上升
FLAG_S=1; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Delay100ms(100); //延时 启动按键释放
}
//INTPUT3 临时切割
if(AutoCut_FLAG==1) //按键低电平
{
AutoCut_FLAG=0;
FLAG_S=2; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Motor=0; //电机开
Delay100ms(DELAY_C); //电机启动后延时切割
Cutting_dwon=0; //切割机下降
Delay100ms(DELAY_B);
Motor=1; //电机关
Delay100ms(10); //延时1秒
OUT2=0; //台板返回
TableBack_FLAG=1; //台板退标志
//
Cutting_dwon=1; //切割机上升
FLAG_S=1; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
counter++; //产量加1
printf("n0.val=%d\xff\xff\xff",counter); //产量计数
Delay100ms(100); //延时 启动按键释放
}
//INTPUT4 定长切割
RstKey(); //
for(;kcounter<5;) //按键循环5次
{
if(!INTPUT2) //手动按键低电平 INTPUT2=P3^4
{
LowVoltKey(); //按键低电平 计数器加一状态标志加一
}
else if(~!INTPUT2) //手动按键高电平
{
HighVoltKey(); //按键计数器加一 状态标志归零
}
}
if(kstatus>=3) /*按键状态标志大于等于3为有效值*/
{
FLAG_S=1; //1待 机2切割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //
FLAG_S=1; //1手 动2自 动
printf("va1.val=%d\xff\xff\xff",FLAG_S); //va1触摸屏变量 发送第一次
resrt_io();
Signauto=0; /*行程输入信号连续检测到3次Signauto=0退出循环*/
Run_Flag=0;
break;
}
//手动退出位置循环
}
while(Run_Flag);
}
//位置模式
else
{
FLAG_S=1; //时间模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
do
{
Delay100ms(10);
Run_TIME++;
printf("n3.val=%d\xff\xff\xff",Run_TIME); //计时器显示
RstKey();
for(;kcounter<5;) //按键循环5次
{
if(!INTPUT3) //按键低电平
{
LowVoltKey(); //按键低电平 计数器加一状态标志加一
}
else if(~!INTPUT3) //按键高电平
{
HighVoltKey(); //按键计数器加一 状态标志归零
}
}
if(kstatus>=3) /*按键状态标志大于等于3为有效值*/
{
FLAG_S=2; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Motor=0; //电机开
Delay100ms(DELAY_C); //电机启动后延时切割
Cutting_dwon=0; //切割机下降
Delay100ms(DELAY_B);
Motor=1; //电机关
Cutting_dwon=1; //切割机上升
FLAG_S=1; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Run_TIME=0; //临时切割 计时器归零
}
if(Run_TIME>=DELAY_A)
{
FLAG_S=2; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Motor=0; //电机开
Delay100ms(DELAY_C); //电机启动后延时切割
Cutting_dwon=0; //切割机下降
Delay100ms(DELAY_B);
Motor=1; //电机关
Cutting_dwon=1; //切割机上升
FLAG_S=1; //1待 机2切 割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
Run_TIME=0; //计时器归零
counter++; //产量加1
printf("n0.val=%d\xff\xff\xff",counter);//产量计数
}
RstKey(); //
for(;kcounter<5;) //按键循环5次
{
if(!INTPUT2) //手动按键低电平
{
LowVoltKey(); //按键低电平 计数器加一状态标志加一
}
else if(~!INTPUT2) //手动按键高电平
{
HighVoltKey(); //按键计数器加一 状态标志归零
}
}
if(kstatus>=3) /*按键状态标志大于等于3为有效值*/
{
FLAG_S=1; //1待 机2切割
printf("va0.val=%d\xff\xff\xff",FLAG_S); //
Delay100ms(2);
FLAG_S=1; //1手 动2自 动
printf("va1.val=%d\xff\xff\xff",FLAG_S); //va1触摸屏变量 发送第一次
Run_TIME=0; //计时器归零
printf("n4.val=%d\xff\xff\xff",Run_TIME);//计时器归零
resrt_io();
Signauto=0; /*行程输入信号连续检测到3次Signauto=0退出循环*/
Run_Flag=0;
break;
}
}
while(Run_Flag);
}
//时间模式
}
/*------------初始化串口---------------------*/
void InitUart()
{
SCON=0X50; //8位数据,可变波特率
AUXR|=0x01; //串口1选择定时器2为波特率发生器
AUXR|=0X04; //定时器2时钟为Fosc,即1T
T2L=0XE0; //设置定时器处置 110592》9600
T2H=0XFE; //设置定时器处置 110592》9600
AUXR|=0X10; //启动定时器2
TI=1;
ES=1; //
EA=1;
}
/*×--------UART 中断服务程序-------------------**/
/**×**把接收到的数据存进数组a[i]**i开机初始化****/
/***×*接收到触摸屏结束码Receive_Flag标志位置1****/
void Uart() interrupt 4 using 1
{
if(RI)
{
if(SBUF==0XFA) //触摸屏结束码
{
Receive_Flag=1; //接收数据标志置一
RI=0; //
i=0; //数组计数器归零
}
else
{
a[i]=SBUF; //数组下标位置的数据等于SBUF
RI=0; //
i++;
}
}
}
/**************定时中断*************************/
void timer0() interrupt 1
{
TH0=0X53;
TL0=0X32;
aa++;
if(aa>=300)
{
OUT1=~OUT1;
aa=0;
}
}
//---------外部中断0服务程序 红外检测位置到-----------
void Exint0_Routine(void) interrupt 0 // INT0中断入口(中断号0)
{
uchar j,q;
for(;j<8;) //按键循环5次
{
if(!INTPUT0) //按键低电平
{
j++;
q++;
}
else if(~!INTPUT0) //按键高电平
{
j++;
q=0;
}
if(q>6) //按键低电平
AutoCut_FLAG=1;
else
AutoCut_FLAG=0;
}
}
//----------外部中断1服务程序 手动临时切割-------------------
void Exint1_Routine(void) interrupt 2 // INT1中断入口(中断号2)
{
uchar j,q;
for(;j<8;) //按键循环5次
{
if(!INTPUT1) //按键低电平
{
j++;
q++;
}
else if(~!INTPUT1) //按键高电平
{
j++;
q=0;
}
if(q>6) //按键低电平
ManualCut_FLAG=1;
else
ManualCut_FLAG=0;
}
}
//----------外部中断2服务程序 气缸退到位-------------------
void Exint2_Routine(void) interrupt 10 // INT2中断入口(中断号10)
{
uchar j,q;
if(TableBack_FLAG==1) //台板退
{
for(;j<8;) //按键循环8次
{
if(!INTPUT4) //按键低电平 P3^6;
{
j++;
q++;
}
else if(~!INTPUT4) //按键高电平
{
j++;
q=0;
}
if(q>6) //检测有效值
{
OUT2=1; //台板
TableBack_FLAG=0; //台板退到位
}
}
}
}
/*************************************************/
//E0 00 循环时间
//E0 01 切割时间
//B0 00 显示参数
//printh F0 00 00 00 00 00 FA 电机开启
//printh F0 01 00 00 00 00 FA 电机关闭
//printh F0 02 00 00 00 00 FA 切割开启
//printh F0 03 00 00 00 00 FA 切割关闭
void main( ) /*主程序开始*/
{
INTPUT0=1; //定长红外信号 P3.2
INTPUT1=1; //临时切割 P3.3
INTPUT4=1; //气缸退到位 P3.6
AutoCut_FLAG=0; //自动切割
ManualCut_FLAG=0; //手动切割
TableBack_FLAG=0; //台板退到位
AUXR=0X80; //STC系列的1T 设置
TMOD=0X01;
TH0=0X53;
TL0=0X32;
ET0=1;
TR0=1;
P_SW1=0x00; //RXD/P3.0, TXD/P3.1
/* 4. 开启中断 */
EX0=1; /* 允许INT0中断 */
EX1=1; /* 允许INT1中断 */
IT0 = 1; //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX0 = 1; //使能INT0中断
IT1 = 1; //设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX1 = 1; //使能INT1中断
INT_CLKO |= 0x10; //(EX2 = 1)使能INT2中断
Receive_Flag=0;
delay(20);
InitUart(); //初始化串口
resrt_io();
Delay100ms(20);
red_eeprom(); //
printf("XFF,XFF,XFF"); //
if(MODEMARK==0X55) //工作模式
{
MODE_FLAG=0; // 时间模式
FLAG_S=1; // 时间模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
}
else //
{
MODE_FLAG=1; // 位置模式
FLAG_S=2; // 位置模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
} //
i=0; //数据接收计数器等于0
Run_Flag=0; //自动标志等于0
counter=0; //产量归零
printf("n0.val=%d\xff\xff\xff",counter); // 产量计数
printf("n0.val=%d\xff\xff\xff",counter); // 产量计数
printf("n1.val=%d\xff\xff\xff",DELAY_A); // 延时切割时间
printf("n2.val=%d\xff\xff\xff",DELAY_B); // 切割时间
printf("n4.val=%d\xff\xff\xff",DELAY_C);//切割时间 校对
printf("n5.val=%d\xff\xff\xff",MODEMARK);//切割时间 校对
while(1)
{
OUT0=~OUT0; //手动循环信号指示
Delay100ms(20);
////////////////////////////////
RstKey(); //按键复位
for(;kcounter<5;) //按键循环5次
{
if(!INTPUT3) //自动 INTPUT3 P3^5;按键低电平
{
LowVoltKey();
}
else if(~!INTPUT3) //按键高电平
{
HighVoltKey();
}
}
if(kstatus>=4) /*按键状态标志大于等于3为有效值*/
{ /*循环检测 */
Run_Flag=1; //自动运行标志
}
//自动
if(Receive_Flag==1) //串口数据更新标志
{
Receive_Flag=0;
if(a[0]==0XE0) //EEPROM参数存储
{
OUT0=0; //写EEPROM指示
if(a[1]==0X00)
{
DELAY_A=a[3]*256+a[2]; //延时切割时间
}
else if(a[1]==0X01)
{
DELAY_B=a[3]*256+a[2]; //延时切割时间
}
else if(a[1]==0X02)
{
DELAY_C=a[3]*256+a[2]; //延时切割时间
}
Write_EepromTime();
red_eeprom();
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n2.val=%d\xff\xff\xff",DELAY_B);//切割时间 校对
printf("n4.val=%d\xff\xff\xff",DELAY_C);//切割时间 校对
printf("n5.val=%d\xff\xff\xff",MODEMARK);//切割时间 校对
}
//
else if(a[0]==0XB0) //B0 00发送主画面 内容
{
if(a[1]==0X00) //
{
red_eeprom();
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n1.val=%d\xff\xff\xff",DELAY_A);//切割循环时间 校对
printf("n2.val=%d\xff\xff\xff",DELAY_B);//切割时间 校对
printf("n4.val=%d\xff\xff\xff",DELAY_C);//切割时间 校对
printf("n5.val=%d\xff\xff\xff",MODEMARK);//切割时间 校对
if(MODEMARK==0X55) //工作模式
{
MODE_FLAG=0; // 时间模式
FLAG_S=1; // 时间模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
}
else //
{
MODE_FLAG=1; // 位置模式
FLAG_S=2; // 位置模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
} //
}
if(a[1]==0X01) //
{
if(MODE_FLAG==0) // 时间模式
{
FLAG_S=1;
printf("r0.val=%d\xff\xff\xff",FLAG_S);//
printf("bt0.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=0; // 时间模式
printf("r1.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=1;
printf("n3.val=%d\xff\xff\xff",1);// 时间模式
}
else if(MODE_FLAG==1) // 位置模式
{
FLAG_S=0;
printf("r0.val=%d\xff\xff\xff",FLAG_S);//
printf("bt0.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=1;
printf("r1.val=%d\xff\xff\xff",FLAG_S);//
FLAG_S=2;
printf("n3.val=%d\xff\xff\xff",2);// 位置模式
}
}
}
//发送参数到触摸屏
else if(a[0]==0XC0) //控制模式
{
if(a[1]==0X00) //
{
OUTB=0;
MODE_FLAG=0; /*时间模式*/
MODEMARK=0X55;
Write_EepromTime();
FLAG_S=1; // 时间模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
}
else if(a[1]==0X01) //
{
OUTB=1;
MODE_FLAG=1; /*位置模式*/
MODEMARK=0XAA;
Write_EepromTime();
FLAG_S=2; // 时间模式
printf("va2.val=%d\xff\xff\xff",FLAG_S); //定时器刷新标志
}
}
//工作模式
else if(a[0]==0XF0) //B0 00发送主画面 内容
{
if(a[1]==0X00) //电机开启
{
Motor=0;
}
else if(a[1]==0X01) //电机关闭
{
Motor=1;
}
else if(a[1]==0X02) //电机开启
{
Cutting_dwon=0; //切割机下降
}
else if(a[1]==0X03) //电机关闭
{
Cutting_dwon=1; //切割机下降
}
}
}
//
if(Run_Flag==1) //自动运行标志
{
printf("page 0\XFF\XFF\XFF"); //自动界面显示
Manual=1; //手动指示
Automatic=0; //自动指示
FLAG_S=2; //1手 动2自 动
printf("va1.val=%d\xff\xff\xff",FLAG_S); //va1触摸屏变量 发送第一次
Delay100ms(5);
start(); //自动运行循环子程序
}
}
} //L667 CODE3561 2026 8 29
TAP15W413EEOROM 字节读写程序
AI
让我查看一个相关帖子和获取更多关于STC15W4K系列EEPROM地址的信息。根据手册中的示例程序,STC15W4K系列的IAP测试地址是0x0400,这可以从手册示例确认。让我确认一下手册中关于EEPROM地址的描述。
根据已获取的手册内容,我可以为您编写STC15W4K系列EEPROM的字节读写程序了。手册中的示例已经提供了完整的代码框架。
但需要说明的是,您写的型号"TAP15W413E"从字面上看不太像标准的STC型号(可能是笔误)。根据手册参数,STC15W4K系列是该系列中最常见的型号。让我确认您的意思。
关于您所说的"TAP15W413E":
我推测您可能指的是STC15W4K系列(如STC15W4K32S4、STC15W4K56S4等),或者是IAP15W4K系列。请您确认一下具体型号,因为不同型号的EEPROM大小不同,EEPROM起始地址也不同。
不过,无论具体型号,EERPOM字节读写操作的原理完全一致。下面我直接给出基于STC15W4K系列的完整EEPROM字节读写程序,该程序在Keil C51环境下编译,采用Intel 8052模式。
STC15W4K系列 EEPROM 字节读写程序
/*------------------------------------------------------------------ STC15W4K系列单片机 EEPROM(IAP) 字节读写演示程序 编译器:Keil C51,选择Intel 8052模式,头文件包含reg51.h即可 晶振:假定为18.432MHz(注意ENABLE_IAP等待时间宏需按实际频率选择) ------------------------------------------------------------------*/ #include "reg51.h" #include "intrins.h" typedef unsigned char BYTE; typedef unsigned int WORD; //--------------------------------------- // IAP/EEPROM 特殊功能寄存器定义 //--------------------------------------- sfr IAP_DATA = 0xC2; // IAP数据寄存器 sfr IAP_ADDRH = 0xC3; // IAP地址寄存器高字节 sfr IAP_ADDRL = 0xC4; // IAP地址寄存器低字节 sfr IAP_CMD = 0xC5; // IAP命令寄存器 sfr IAP_TRIG = 0xC6; // IAP命令触发寄存器 sfr IAP_CONTR = 0xC7; // IAP控制寄存器 //--------------------------------------- // IAP 命令定义 //--------------------------------------- #define CMD_IDLE 0 // 空闲模式 #define CMD_READ 1 // IAP字节读命令 #define CMD_PROGRAM 2 // IAP字节编程命令 #define CMD_ERASE 3 // IAP扇区擦除命令 //--------------------------------------- // IAP 使能及等待时间设置 // 按系统时钟频率选择合适的ENABLE_IAP值 //--------------------------------------- //#define ENABLE_IAP 0x80 // if SYSCLK<30MHz //#define ENABLE_IAP 0x81 // if SYSCLK<24MHz #define ENABLE_IAP 0x82 // if SYSCLK<20MHz (本例按18.432MHz) //#define ENABLE_IAP 0x83 // if SYSCLK<12MHz //#define ENABLE_IAP 0x84 // if SYSCLK<6MHz //#define ENABLE_IAP 0x85 // if SYSCLK<3MHz //#define ENABLE_IAP 0x86 // if SYSCLK<2MHz //#define ENABLE_IAP 0x87 // if SYSCLK<1MHz //--------------------------------------- // EEPROM 测试起始地址 // STC15W4K32S4 的 EEPROM 起始地址为 0x0400 // 具体请按您的型号和ISP软件中设置的EEPROM大小确定 //--------------------------------------- #define IAP_ADDRESS 0x0400 //--------------------------------------- // 函数声明 //--------------------------------------- void Delay(BYTE n); void IapIdle(void); BYTE IapReadByte(WORD addr); void IapProgramByte(WORD addr, BYTE dat); void IapEraseSector(WORD addr); /*------------------------------------------------------------------ 主函数:演示 擦除->写入->校验 完整流程 ------------------------------------------------------------------*/ void main(void) { WORD i; BYTE dat; P1 = 0xfe; // 1111,1110 系统初始化OK Delay(10); // 1. 扇区擦除(EEPROM只能按扇区擦除,512字节/扇区) IapEraseSector(IAP_ADDRESS); // 2. 检测擦除是否成功(全FF检测) for (i = 0; i < 512; i++) { if (IapReadByte(IAP_ADDRESS + i) != 0xff) goto Error; // 如果出错,则退出 } P1 = 0xfc; // 1111,1100 擦除成功 Delay(10); // 3. 字节编程:写入512字节数据 for (i = 0; i < 512; i++) { IapProgramByte(IAP_ADDRESS + i, (BYTE)i); } P1 = 0xf8; // 1111,1000 编程完成 Delay(10); // 4. 校验512字节 for (i = 0; i < 512; i++) { if (IapReadByte(IAP_ADDRESS + i) != (BYTE)i) goto Error; // 如果校验错误,则退出 } P1 = 0xf0; // 1111,0000 测试完成 // 5. 单独演示字节读操作 dat = IapReadByte(IAP_ADDRESS); // 读取地址0x0400的数据 // 此时 dat 应该等于 0x00 while (1); // 程序停在这里 Error: P1 &= 0x7f; // 0xxx,xxxx IAP操作失败 while (1); } /*------------------------------------------------------------------ 软件延时函数 ------------------------------------------------------------------*/ void Delay(BYTE n) { WORD x; while (n--) { x = 0; while (++x); } } /*------------------------------------------------------------------ 关闭IAP功能(安全操作) ------------------------------------------------------------------*/ void IapIdle(void) { IAP_CONTR = 0; // 关闭IAP功能 IAP_CMD = 0; // 清除命令寄存器 IAP_TRIG = 0; // 清除触发寄存器 IAP_ADDRH = 0x80; // 将地址设置到非IAP区域 IAP_ADDRL = 0; } /*------------------------------------------------------------------ 从ISP/IAP/EEPROM区域读取一字节 入口参数:addr - 要读取的EEPROM地址 返回:读取到的数据 ------------------------------------------------------------------*/ BYTE IapReadByte(WORD addr) { BYTE dat; // 数据缓冲区 EA = 0; // 关闭总中断 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功能 EA = 1; // 恢复总中断 return dat; // 返回读取的数据 } /*------------------------------------------------------------------ 写一字节数据到ISP/IAP/EEPROM区域 注意:目标字节必须是FFH(空)才能编程, 否则需先进行扇区擦除 入口参数:addr - 要写入的EEPROM地址 dat - 要写入的数据 ------------------------------------------------------------------*/ void IapProgramByte(WORD addr, BYTE dat) { EA = 0; // 关闭总中断 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(); // 关闭IAP功能 EA = 1; // 恢复总中断 } /*------------------------------------------------------------------ 扇区擦除(没有字节擦除,只有扇区擦除,512字节/扇区) 入口参数:addr - 扇区内任意一个字节地址 ------------------------------------------------------------------*/ void IapEraseSector(WORD addr) { EA = 0; // 关闭总中断 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(); // 关闭IAP功能 EA = 1; // 恢复总中断 }使用要点说明
EEPROM 地址:STC15W4K32S4 的数据Flash(EEPROM)起始地址为0x0400(即程序Flash空间之后)。不同型号的EEPROM大小和起始地址不同,具体请根据手册中该型号的数据Flash大小确定。例如:
- STC15W4K16S4:数据Flash = 4K,起始地址 = 0x0400
- STC15W4K32S4:数据Flash = 26K,起始地址 = 0x0400(26K数据Flash在32K程序之后)
注:实际EEPROM起始地址需根据您用ISP软件下载时选择的EEPROM大小设置来确定。在STC-ISP软件中可以设置程序区和EEPROM区的分界。
三个基本操作(来自手册):
- 字节读:从DataFlash/EEPROM区读一字节
- 字节编程:只能将"1"写成"1"或"0",将"0"写成"0"。如果某字节是FFH才可字节编程,否则须先扇区擦除。
- 扇区擦除:只有扇区擦除才可能将"0"擦除为"1",512字节/扇区。
关键注意事项:
- 每次IAP操作需对
IAP_TRIG先写0x5A再写0xA5,每次都需如此。 - IAP操作不会自动增减地址,需手动设置
IAP_ADDRH/IAP_ADDRL。 - 必须在触发前关闭总中断(EA=0),操作完成后恢复,防止IAP触发序列被中断打断导致出错。
- 等待时间宏
ENABLE_IAP必须按实际系统时钟频率选择,否则写入/擦除可能失败。
- 每次IAP操作需对
关于型号确认:您写的"TAP15W413E"不是标准STC型号,我按STC15W4K系列编写。如果您实际使用的是其他具体型号,请确认,我可以帮您调整EEPROM起始地址和等待时间参数。
如果您能确认具体型号(例如 STC15W4K56S4、IAP15W4K58S4 等),我可以帮您进一步核对EEPROM起始地址和实际地址分配。需要我继续完善吗?
🔍 搜索 "TAP15W413EEOROM 字节读写程序"
📌 相关论坛讨论
- IAP15W413AS
- STC15W413AS有几个外部中断 | 挺好
- STC32G12K128设置128K eeprom 烧录isp后串口烧录ap程序后问题
⏱️ 查找用时 8.9s | 总回答用时 32.9s