⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleplcfunc.c

📁 AVR典型实例.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
   简易PLC功能 
   作者:吴健
   编写日期:2008年1月2日-1月3日
   版本:1.0 测试完成
   软件支持:输入触点、输出继电器、中间继电器,定时器、计数器

*/
#include <avr\io.h>
#include "SimplePLC.h"


// 时间变量
struct STime{
	unsigned char count;  // 多少个0.01秒
	unsigned char second; // 秒
	unsigned char minute; // 分钟
	unsigned char hour;   // 小时
	unsigned char day ;   // 日期
	unsigned char month;  // 月份
	unsigned char year;   // 年
}now,Timer[MAX_TIMER]; // 当前时间、MAX_TIMER组定时器
unsigned char TimerMutex[MAX_TIMER];     // MAX_TIMER组定时器的运行信号
unsigned char TimerAddMutex[MAX_TIMER];  // MAX_TIMER组增加定时器时间的运行信号
unsigned char TimerSubMutex[MAX_TIMER];  // MAX_TIMER组减少定时器时间的运行信号
unsigned char year_err = 0;  // 年份减法出错位,0:正常,1:出错

unsigned int INPORT=0,OUTPORT=0; // 虚拟输入输出端口,各16个节点
unsigned char tmpPORT[MAX_TMPPORT];  // 暂存的变量
unsigned char cur_tmp_p = 0; // 当前的暂存变量

unsigned int APORT[MAX_APUT];   // 中间触点
unsigned int stack_op[STACK_MAX];  // 堆栈
signed char stack_p=-1; // 堆栈指针
unsigned char stack_err = 0; // 堆栈错误

// 计数器变量
#ifdef _PLC_USE_C_
unsigned int Counter[MAX_COUNTER]; // 最大计数长度65535
unsigned char CounterOut[MAX_COUNTER]; // 计数器计数到达后的输出状态,0表示未到达,1表示到达
unsigned char CounterNowValue[MAX_COUNTER];  // 计数器当前值
#endif

// 定时器0的溢出中断
SIGNAL(SIG_OVERFLOW0)
{
	now.count++;
	if(now.count == 99)
	{
		now.second++;
		now.count = 0;

	}
	TCNT0 = 256 - 0.01/(1024.0/F_CPU);
	sei();	

} 

// 堆栈处理函数
// 数据压栈
void push_stack(unsigned int dat)
{
    if(stack_p < STACK_MAX)
	{
	    stack_p++;
		stack_op[stack_p] = dat;
	}
}
// 数据出栈
unsigned int pop_stack(void)
{
    unsigned int tmp;
	if(stack_p > -1)
	{
	    tmp = stack_op[stack_p];
		stack_p--;
		stack_err = 0;
		return tmp;
	}
	stack_err = 1; // 堆栈错误
	return 0;
}
// 清除堆栈中所有的元素
void clear_stack(void)
{
	stack_p = -1;
    stack_err = 0;
}
// 得到栈顶的元素
unsigned int gettop_stack(void)
{
    if(stack_p > -1)
	{
	    stack_err = 0;
		return stack_op[stack_p];
	}else{
		stack_err = 1;
		return 0;
	}
}
void PUSH_STACK()
{
    push_stack(tmpPORT[cur_tmp_p]); // 压栈命令
}
// 动作
// 取常开输入输出和中间触点
void LD(unsigned char a)  
{
    unsigned char tmp = tmpPORT[cur_tmp_p];
    wdt_reset();  // 喂狗,表示程序在正常运行
    if(a<MAX_INPUT)  // 输入触点
	{
		if(Get_Bit(INPORT,a))
			tmp = tmp & 1;
    	else
	    	tmp = 0;
	}else if(a<OUTPUT_TOP){  // 输出触点
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
			tmp = tmp & 1;
    	else
	    	tmp = 0;

	}else if(a<APUT_TOP){  // 中间触点
		a -= OUTPUT_TOP;
		if(APORT[a])
			tmp = tmp & 1;
    	else
	    	tmp = 0;
	}else{  // 计数器触点
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmp = tmp & 1;
        else
		    tmp = 0;
	}
	tmpPORT[cur_tmp_p] = tmp;
}
// 取常闭输入输出和中间触点
void NLD(unsigned char a)  
{
    unsigned char tmp = tmpPORT[cur_tmp_p];
	wdt_reset();  // 喂狗,表示程序在正常运行
    if(a<MAX_INPUT)  // 输入触点
	{
		if(Get_Bit(INPORT,a)>>a)
			tmp =  0;
    	else
	    	tmp = tmp & 1;
	}else if(a<OUTPUT_TOP){  // 输出触点
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a)>>a)
			tmp = 0;
    	else
	    	tmp = tmp& 1;

	}else if(a<APUT_TOP){  // 中间触点
		a = a - OUTPUT_TOP;
		if(APORT[a])
			tmp =  0;
    	else
	    	tmp = tmp & 1;
	}else{  // 计数器触点
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmp = 0;
        else
		    tmp = tmp & 1;
	}
	tmpPORT[cur_tmp_p] = tmp;
}
// 初始化取触点
void ST(unsigned char a)
{
    unsigned char tmp = tmpPORT[cur_tmp_p];
	clear_stack();
	wdt_reset();  // 喂狗,表示程序在正常运行
    if(a<MAX_INPUT)  // 输入触点
	{
		if(Get_Bit(INPORT,a))
			tmp = 1;
    	else
	    	tmp = 0;
	}else if(a<OUTPUT_TOP){  // 输出触点
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
			tmp  = 1;
    	else
	    	tmp =  0;

	}else if(a<APUT_TOP){  // 中间触点
		a = a - OUTPUT_TOP;
		if(APORT[a])
			tmp =  1;
    	else
	    	tmp = 0;
	}else{  // 计数器触点
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmp = 1;
        else
		    tmp = 0;
	}
	tmpPORT[cur_tmp_p] = tmp;
}

// 常开逻辑与输入输出和中间触点
void AND(unsigned char a)
{
    unsigned char tmp = tmpPORT[cur_tmp_p];

    if(a < MAX_INPUT)
	{
		if(Get_Bit(INPORT,a))
	    	tmp = tmp & 1;
    	else
	    	tmp = 0; 
	}else if(a<OUTPUT_TOP){
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
	    	tmp = tmp & 1;
    	else
	    	tmp = 0; 

	}else if(a<APUT_TOP){  // 中间触点
		a = a - OUTPUT_TOP;
		if(APORT[a])
			tmp =  tmp & 1;
    	else
	    	tmp = 0;
	}else{  // 计数器触点
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmp = tmp & 1;
        else
		    tmp = 0;
	}
	tmpPORT[cur_tmp_p] = tmp;
}

// 常闭逻辑与输入触点
void NAND(unsigned char a)
{
    unsigned char tmp = tmpPORT[cur_tmp_p];
    if(a < MAX_INPUT)
	{
		if(Get_Bit(INPORT,a))
	    	tmp = 0;
    	else
	    	tmp = tmp & 1; 
	}else if(a<OUTPUT_TOP){
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
	    	tmp = 0;
    	else
	    	tmp = tmp & 1; 

	}else if(a<APUT_TOP){  // 中间触点
		a = a - OUTPUT_TOP;
		if(APORT[a])
			tmp =  0;
    	else
	    	tmp = tmp & 1;
	}else{  // 计数器触点
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmp = 0;
        else
		    tmp = tmp & 1;
	}
	tmpPORT[cur_tmp_p] = tmp;
}
// 并联常开输入输出和中间触点
void OR(unsigned char a)
{
	unsigned int tmp;
	unsigned char tmpPORT1;
	tmpPORT1 = tmpPORT[cur_tmp_p];
    tmp = gettop_stack();
    if(stack_err == 1)
	    tmp = 1;

    if(a < MAX_INPUT)
	{   
		if(Get_Bit(INPORT,a))
	    	tmpPORT1 = (tmp & 1)|tmpPORT1;
    	else
	    	tmpPORT1 = (0)|tmpPORT1;
	}else if(a<OUTPUT_TOP){
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
	    	tmpPORT1 = (tmp & 1)|tmpPORT1;
    	else
	    	tmpPORT1 = (0)|tmpPORT1; 

	}else if(a<APUT_TOP){
		a = a - OUTPUT_TOP;
		if(APORT[a])
	    	tmpPORT1 = (tmp & 1)|tmpPORT1;
    	else
	    	tmpPORT1 = (0)|tmpPORT1; 
	}else{
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmpPORT1 = (tmp &1)|tmpPORT1;
		else
		    tmpPORT1 = 0|tmpPORT1;
	}
	tmpPORT[cur_tmp_p] = tmpPORT1;
}
// 并联常闭输入输出和中间触点
void NOR(unsigned char a)
{
	unsigned int tmp;
	unsigned char tmpPORT1;
	tmpPORT1 = tmpPORT[cur_tmp_p];
    tmp = gettop_stack();
    if(stack_err == 1)
	    tmp = 1;
    if(a < MAX_INPUT)
	{   
		if(Get_Bit(INPORT,a))
	    	tmpPORT1 = (0)|tmpPORT1;
    	else
	    	tmpPORT1 = (tmp & 1)|tmpPORT1;
	}else if(a<OUTPUT_TOP){
		a = a - MAX_INPUT;
		if(Get_Bit(OUTPORT,a))
	    	tmpPORT1 = (0)|tmpPORT1;
    	else
	    	tmpPORT1 = (tmp & 1)|tmpPORT1; 

	}else if(a<APUT_TOP){
		a = a - OUTPUT_TOP;
		if(APORT[a])
	    	tmpPORT1 = (0)|tmpPORT1;
    	else
	    	tmpPORT1 = (tmp & 1)|tmpPORT1; 
	}else{
        a -= APUT_TOP;
		if(CounterOut[a])
		    tmpPORT1 = 0|tmpPORT1;
		else
		    tmpPORT1 = (tmp &1)|tmpPORT1;
	}
	tmpPORT[cur_tmp_p] = tmpPORT1;
}
// 得到堆栈的最顶部元素,并切换到下一路电路
void GETNEXT(void)
{
	unsigned char tmp;
	tmp = gettop_stack();
    if(cur_tmp_p<MAX_TMPPORT)
	{
		cur_tmp_p++;
		tmpPORT[cur_tmp_p] = tmp;
	}
}
// 以或的方式合并所有的电路
void TOTAL(void)
{
	unsigned char tmp=tmpPORT[0];
	unsigned char i;
	for(i=1;i<=cur_tmp_p;i++)
	{
		tmp = tmp | tmpPORT[i];
	}
	tmpPORT[0] = tmp;
	cur_tmp_p = 0;

}

// 输出输出和中间触点
void OUT(unsigned char a)
{
	unsigned char tmpPORT1;
	wdt_reset();  // 喂狗,表示程序在正常运行
	tmpPORT1 = tmpPORT[cur_tmp_p];
    if((a>(MAX_INPUT-1))&&(a<OUTPUT_TOP)) // 输出触点
	{
	    a = a - MAX_INPUT;
		if(tmpPORT1)
			Set_Bit(OUTPORT,a); 
		else
			Clr_Bit(OUTPORT,a);
    }else if((a>=OUTPUT_TOP)&&(a<APUT_TOP)){  // 中间触点
		a = a - OUTPUT_TOP;
		if(tmpPORT1)
			APORT[a] = 1; 
		else
			APORT[a] = 0;

	}

}
// 程序刷新输出继电器
void END(void)
{
    wdt_reset();  // 喂狗,表示程序在正常运行
	PORTC = OUTPORT&0xff;
	PORTD = (OUTPORT>>8)&0xff; 
} 
// 程序刷新输入继电器
void BEG(void)
{

	INPORT = PINA+(PINB<<8);
	    
    cur_tmp_p = 0;  // 当前暂存变量序号
	year_err = 0;  // 清年份出错位
	clear_stack();
    AutoTime();
}

// 初始化定时器

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -