📄 main_cv__.c
字号:
//ICC-AVR application builder : 2004-8-22 19:49:01
// Target : M16
// Crystal: 16.000Mhz
//本程序所用的长度单位为毫米,时间单位为8个时钟周期(千万分之五秒)
#include <Mega16.h>
//#include <macros.h>
#include <h_iic.c>
#include <Mega16.h>
#include <string.h>
#include <delay.h>
//TWI状态定义
//MT 主方式传输 MR 主方式接收
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
//hardware IIC
#define TWINT 7
#define TWEA 6
#define TWSTA 5
#define TWSTO 4
#define TWEN 2
//常用TWI操作(主模式写和主模式读)
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait() {while(!(TWCR&(1<<TWINT)));}
#define TestAck() (TWSR&0xf8)
#define SetAck() (TWCR|=(1<<TWEA))
#define SetNoAck() (TWCR&=~(1<<TWEA))
#define TWI() (TWCR=(1<<TWINT)|(1<<TWEN))
#define TWE() (TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN))
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
#define zlg7290 0x70
/******************************************
I2C总线写字符串
返回0:写成功
返回非0:写失败
*******************************************/
unsigned char ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{ unsigned char i;
#asm("cli")
Start();//I2C启动
Wait();
if(TestAck()!=START){Stop(); return 1;} //ACK
Write8Bit(sla);//写I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK){Stop(); return 1;} //ACK
Write8Bit(suba);//写地址
for(i=0;i<no;i++)
{ Wait();
if(TestAck()!=MT_DATA_ACK){Stop(); return 1;}//ACK
Write8Bit(*s);//写数据
s++;
}
Wait();
if(TestAck()!=MT_DATA_ACK){Stop(); return 1;} //ACK
Stop();//I2C停止
#asm("sei")
return 0;
}
/******************************************
I2C总线读字符串
如果读失败也返回0,正确返回1;
*******************************************/
unsigned char IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
#asm("cli")
Start();//I2C启动
Wait();
if (TestAck()!=START) {Stop(); return 0;}//ACK
Write8Bit(sla);//写I2C从器件地址和写方式
Wait();
if (TestAck()!=MT_SLA_ACK) {Stop(); return 0;}//ACK
Write8Bit(suba);//写地址
Wait();
if (TestAck()!=MT_DATA_ACK) {Stop(); return 0;}
Start();//I2C重新启动
Wait();
if (TestAck()!=RE_START) {Stop(); return 0;}
Write8Bit(sla+1);//写I2C从器件地址和读方式
Wait();
if(TestAck()!=MR_SLA_ACK) {Stop(); return 0;}//ACK
for(i=0;i<no-1;i++)
{ TWE();//启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_ACK) {Stop(); return 0;};//ACK
*s=TWDR;//读取I2C接收数据
s++;
}
TWI();//启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK) {Stop(); return 0;}//ACK
*s=TWDR;//读取I2C接收数据
Stop();//I2C停止
#asm("sei")
return 1;
}
unsigned char ZLG7290_SendData(unsigned char SubAdd,unsigned char Data)
{
if(SubAdd>0x17)
return 0;
ISendStr(zlg7290,SubAdd,&Data,1);
delay_ms(10);
return 1;
}
//向zlg7290命令缓冲区发送命令(2个字节)
unsigned char ZLG7290_SendCmd(unsigned char Data1,unsigned char Data2)
{
unsigned char Data[2];
Data[0]=Data1;
Data[1]=Data2;
ISendStr(zlg7290,0x07,Data,2);
delay_ms(10);
return 1;
}
//向zlg7290的显示缓冲区发送数据
void ZLG7290_SendBuf(unsigned char *display_buf,unsigned char num)
{
unsigned char i;
for(i=0;i<num;i++)
{
ZLG7290_SendCmd(0x60+i,*display_buf);
display_buf++;
}
}
//zlg7290的键值
unsigned char ZLG7290_GetKey()
{ unsigned char rece=0;
if( IRcvStr(zlg7290,1,&rece,1)==0 ) return (0);
delay_ms(10);
return rece;
}
//向ZLG7290发送字符串
void disstring(char *tmp)
{
unsigned char num;
unsigned char i;
unsigned char chr,chr1,chr2;
char *at;
num=strlen(tmp);
//at=strchr(tmp,46);
//if (at[0]==0) num=num-1;
//if (num>=8) num=8;
at=tmp;
if (num>8)
{
if (*at==46) num=9;
at++;
}
for (i=0;i<num;i++)
{
chr=0x68-i;
chr=*tmp;
switch (chr)
{
case '0' : chr1=0; break;
case '1' : chr1=1; break;
case '2' : chr1=2; break;
case '3' : chr1=3; break;
case '4' : chr1=4; break;
case '5' : chr1=5; break;
case '6' : chr1=6; break;
case '7' : chr1=7; break;
case '8' : chr1=8; break;
case '9' : chr1=9; break;
case ' ' : chr1=31; break;
case 'A' : chr1=10; break;
case 'b' : chr1=11; break;
case 'C' : chr1=12; break;
case 'd' : chr1=13; break;
case 'E' : chr1=14; break;
case 'F' : chr1=15; break;
case 'G' : chr1=16; break;
case 'H' : chr1=17; break;
case 'i' : chr1=18; break;
case 'J' : chr1=19; break;
case 'L' : chr1=20; break;
case 'O' : chr1=21; break;
case 'P' : chr1=22; break;
case 'q' : chr1=23; break;
case 'r' : chr1=24; break;
case 't' : chr1=25; break;
case 'U' : chr1=26; break;
case 'y' : chr1=27; break;
case 'c' : chr1=28; break;
case 'h' : chr1=29; break;
case 'T' : chr1=30; break;
case '.' : chr1=128; break;
default : chr1=31;
}
tmp++;
chr2=*tmp;
if (chr2=='.')
{
chr1=chr1+128;
tmp++;
}
ZLG7290_SendCmd(chr,chr1);
}
}
//#include <eeprom.h>
#include <stdlib.h>
/////////////// 键盘定义
#define START_K 1
//启动
#define ENTER 1
//确定
#define STOP 5
//停止
#define RETURN 5
//返回
#define K1 2
//1
#define INC_SPEED 2
//增速
#define K2 3
//2
#define DEC_SPEED 3
//减速
#define K3 4
//4
#define SET 4
//设定
#define K4 6
//4
#define SPEED 6
//速度
#define K5 7
//5
#define COUNT 7
//计数
#define K6 8
//8
#define SUM 8
//累计
#define K0 9
//9
#define CLEAR 9
//清零
#define K7 10
//7
#define MIAN_LENGTH 10
//面长
#define K8 11
//8
#define CUT_NUM 11
//刀数
#define K9 12
//9
#define JIGAN 12
//积杆
#define M_ZHUANBI 4000
//转刀一周步进电机的步数
/////////////// 全局变量定义
unsigned char M_state=0; //步进电机的运行状态
/*
0:停转
1:启动
2:减速至停转
3:加速至随动
4:减速至随动
5:随动
6:加速至碎刀
7:碎刀
8:转动至平行
*/
unsigned int step_num=0; //步进电机相对平行点的占步数
//unsigned char M_maichong; //步进电机的脉冲
unsigned int tmp_t1=64536; //计时器1的当前数值
unsigned char qidong_num=0; //启动过程中步进电机所走的占步数
unsigned char dec_speed_bz=0; //启动减速标志
unsigned int dec_speed_num=0; //减速所走的步数
float DW_juli; //单位距离
float P_speed; //皮带速度
float juli; //切刀到杆切点的距离
unsigned char time0_chi; //计时器0的次数(256的倍数)
unsigned char time0_yu; //计时器0的余数(整除256后所得的余数)
unsigned char time0_fen; //如果余数太小,则从次数中分出一次来,和余数加在一起分担剩余的时间
unsigned char pidai_yunxing=0; //皮带运行:1表示正常运行,0表示停止运行
eeprom float set_speed; //设定的转速******
unsigned char dj_jibie=0; //电磁调速电动机速度增减的级别
unsigned char dj_fangxi=0; //电磁调速电动机调速的方向
unsigned char on_scr=0; //可控硅导通标志
unsigned int pre_jsq=2000; //上一次可控硅触发计时
unsigned char key=0; //按键的键值
unsigned char on_key=0; //有键按下的标志
unsigned char key_num=0; //计数,每计50查一次按键
unsigned char next_gan=0; //过下一杆标志
unsigned char guogan=0; //开始正式过杆的标志
eeprom float dw_speed=0.00000025; //一个时间单位所走的毫米数*******
float ganwei; //杆位:挂面杆相对于切点的位置
float next_ganwei; //下一杆的杆位
eeprom float juli_jcd; //检测点到切点的距离*******
eeprom float ganju; //两根挂面杆的距离*******
eeprom float longth_guamian; //切好的挂面的长度*******
eeprom float longth_zongmian; //一杆上挂面的总长度*******
unsigned char jidao; //一杆面共切几刀
unsigned char first_gan=1; //第一杆标志
unsigned char qidong=0; //步进电机是否起动
unsigned char jileigan=0; //累积的杆数
eeprom unsigned char max_ganshu=10; //积累杆数的上限
unsigned char caoshu=0; //高速标志
float current_speed; //当前速度
eeprom float caogan_speed; //高速时的速度
unsigned char menu_jb=0; //菜单级别
unsigned char menu_gn=0; //菜单功能码
char *string1;
char string2[]=" PASS";
char tmp_string[9]; //输入参数时,显示的数字
unsigned char cs_num=0; //当前参数的位数
char *str_dis;
///////////////
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0xF0;
DDRB = 0xF0;
PORTC = 0x00; //m103 output only
DDRC = 0xC0;
PORTD = 0x00;
DDRD = 0x00;
}
#define ADC_VREF_TYPE 0xC0
unsigned int read_adc(void) //读取模数转换的值,即测速发电机的电压值
{
unsigned char adc_H,adc_L;
unsigned int adc_jg;
adc_L=ADCL;
adc_H=ADCH;
adc_jg=adc_H*256+adc_L;
return adc_jg;
}
//TIMER0 initialize - prescale:8
// WGM: Normal
// desired value: 1Hz
// actual value: Out of range
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x00 /*INVALID SETTING*/; //set count
OCR0 = 0x00 /*INVALID SETTING*/; //set compare
TCCR0 = 0x02; //start timer
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
unsigned char i;
if (on_scr==1) //如果可控硅触发标志为1,则触发可控硅
{
TCCR0=0;
PORTC=PORTC | 0b01000000;
for (i=0;i<20;i++) ;
PORTC=PORTC & 0b10111111;
on_scr=0;
}
if (time0_chi>0) //如果计数器0次数大于0,则重新开始(0-255)的计时
{
TCNT0=0;
TCCR0=2;
time0_chi--;
}
else
{
if (time0_fen>0)
{
TCNT0=time0_fen;
TCCR0=2;
time0_fen=0;
}
else
{
TCNT0=time0_yu;
TCCR0=2;
on_scr=1;
}
}
}
//TIMER1 initialize - prescale:8
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x00 /*INVALID SETTING*/; //setup
TCNT1L = 0x00 /*INVALID SETTING*/;
OCR1AH = 0x00 /*INVALID SETTING*/;
OCR1AL = 0x00 /*INVALID SETTING*/;
OCR1BH = 0x00 /*INVALID SETTING*/;
OCR1BL = 0x00 /*INVALID SETTING*/;
//OCR1CH = $OCR1CH$;
//OCR1CL = $OCR1CL$;
ICR1H = 0x00 /*INVALID SETTING*/;
ICR1L = 0x00 /*INVALID SETTING*/;
TCCR1A = 0x00;
TCCR1B = 0x02; //start Timer
}
interrupt [TIM1_OVF] void timer1_ovf_isr(void) //步进电机控制
{
unsigned char i; //循环变量
unsigned int time1_jsq; //time1的时间值
unsigned int avg_speed; //平均速度
if (M_state==0) //停止状态
{
return;
}
//TIMER1 has overflowed
TCNT1 = tmp_t1; //计数器赋初值
PORTC |=0b10000000; //给出步进电机驱动脉冲
for (i=0;i<5;i++);
PORTC &=0b01111111;
step_num++; //计步加一
time1_jsq=65535-tmp_t1+1;;
switch (M_state)
{
case 1: //启动状态
{
qidong_num++;
tmp_t1=64536;
if (qidong_num>160)
{
M_state=3; //结束启动状态,转入加速状态
}
} break;
case 2: //减速至停转
{
if (time1_jsq<1000) time1_jsq++;
tmp_t1=65535-time1_jsq+1;
if (dec_speed_bz==1)
{
dec_speed_bz=0;
if (step_num>(M_ZHUANBI*3/4)) dec_speed_num=2*M_ZHUANBI-step_num; else dec_speed_num=M_ZHUANBI-step_num;
}
dec_speed_num--;
if (dec_speed_num==0) M_state=0;
} break;
case 3: //加速至随动
case 4: //减速至随动
{
avg_speed=(unsigned int)((juli/(1000-step_num))/P_speed+0.5);
if (avg_speed>time1_jsq) time1_jsq++;
if (avg_speed<time1_jsq) time1_jsq--;
tmp_t1=65535-time1_jsq+1;
if (step_num==999) M_state=5;
} break;
case 5: //随动
{
time1_jsq=(unsigned int)(DW_juli/P_speed);
tmp_t1=65535-time1_jsq+1;
} break;
case 6: //加速至碎刀
{
if (time1_jsq>111) time1_jsq--;
tmp_t1=65535-time1_jsq+1;
if (time1_jsq==111) M_state=7;
} break;
case 7: //碎刀
{
time1_jsq=111;
tmp_t1=65425;
} break;
case 8: //转动至平行
{
if (step_num==0) M_state=0;
tmp_t1=64536;
time1_jsq=1000;
} break;
}
juli=juli-P_speed*time1_jsq;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -