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

📄 hzmmisub18.c

📁 ATMEL的ATMEGA128驱动160×80液晶调试程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
}
//显示小ASCII串
void str_sasc(byte row,byte col,byte *str)
{
	byte q,j;
	word lram;

	lram=row*20+col;

	for(;*str;)
	{
		if(lram>=76*20)
			return;
		q=(*str++);
		if(q==13)
		{
			lram+=20*8;
			continue;
		}

		lib_addr.l=q*8l+0x100l;
		lib_addr_out();

		for(j=0;j<8;j++)
		{
			disp_order_data(0x0a,(byte)lram);
			disp_order_data(0x0b,(byte)(lram/256));
			disp_order(0x0c);
			lib_data();
			PORTC++;

			lram+=20;
		}
		lram=lram-20*8+1;
		if((lram%20)==0)
			lram+=20*7;
	}
}
//居中显示汉字串
void mediacy_hz(byte row,byte* str)
{
	byte i;
	i=strlen(str);
	if(i>=20)
		str_hz(row,0,str);
	else
		str_hz(row,10-i/2,str);
}
//让DS1302时钟芯片写使能
void time_wr_en(void)
{
	byte i;
	byte addr;

	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB|=RST_TM;//让DS1302操作使能,并作适当延时

	addr=0x8f;//0x81为读
	for(i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	PORTB&=~SPI_MI;
	DDRB&=~SPI_MI;//置spi_mosi为输入
	for(addr=0,i=0;i<8;i++)
	{
		addr>>=1;
		if(PINB&SPI_MI)
			addr|=0x80;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
	}
	DDRB|=SPI_MI;
	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB&=~RST_TM;
	if(addr==0)//如果已是写使能状态,则不用再设置了
		return;

	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB|=RST_TM;//让DS1302操作使能,并作适当延时
	
	addr=0x8e;//0x80为写
	for(i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	PORTB&=~SPI_MI;
	for(i=0;i<8;i++)
	{
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
	}
	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB&=~RST_TM;
}
//对DS1302秒读
byte time_sec_rd(void)
{
	byte i;
	byte addr;

	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB|=RST_TM;//让DS1302操作使能,并作适当延时
	
	addr=0x81;//0x81为读
	for(i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	PORTB|=SPI_MI;
	DDRB&=~SPI_MI;//置spi_mosi为输入
	for(addr=0,i=0;i<8;i++)
	{
		addr>>=1;
		if(PINB&SPI_MI)
			addr|=0x80;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
	}
	DDRB|=SPI_MI;
	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB&=~RST_TM;
	return addr;
}
//对DS1302串读
//读取当前时间,依序为:秒分时日月年
void time_str_rd(byte *tdata)
{
	byte i,j;
	byte addr;

	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB|=RST_TM;//让DS1302操作使能,并作适当延时

	addr=(31<<1)|0x81;//0x81为读
	for(i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	PORTB|=SPI_MI;
	DDRB&=~SPI_MI;//置spi_mosi为输入
	for(j=0;j<9;tdata[j]=addr,j++)
	for(addr=0,i=0;i<8;i++)
	{
		addr>>=1;
		if(PINB&SPI_MI)
			addr|=0x80;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
	}
	DDRB|=SPI_MI;
	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB&=~RST_TM;
	tdata[5]=tdata[6];//调整年的顺序
}
//对DS1302串写
//修改当前时间,依序为:秒分时日月年
void time_str_wr(byte *tdata)
{
	byte i,j;
	byte addr;

	if((tdata[5]-0)>(0x99-0))tdata[5]=0;
	if((tdata[4]-1)>(0x12-1))tdata[4]=1;
	if((tdata[3]-1)>(0x31-1))tdata[3]=1;
	if((tdata[2]-0)>(0x23-0))tdata[2]=0;
	if((tdata[1]-0)>(0x59-0))tdata[1]=0;
	if((tdata[0]-0)>(0x59-0))tdata[0]=0;

	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB|=RST_TM;//让DS1302操作使能,并作适当延时

	tdata[6]=tdata[5];//调整年的顺序
	tdata[7]=0;//写使能
	tdata[8]=0xab;//充电模式
	addr=(31<<1)|0x80;//0x80为写
	for(i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	for(j=0;j<9;j++)
	for(addr=tdata[j],i=0;i<8;i++)
	{
		if(addr&1)
			PORTB|=SPI_MI;
		else
			PORTB&=~SPI_MI;
		PORTB|=SPI_SCK;
		PORTB&=~SPI_SCK;
		addr>>=1;
	}
	for(i=0;i<((T_RELOAD+50)/2000);i++)
		PORTB&=~RST_TM;
}
//在屏幕指定行显示时间
void disp_time(byte row)
{
	byte i;
	byte str[21];

	str[0]='2';
	str[1]='0';
	for(;mstimer2<2;);
	for(i=5;i<6;i--)
		csprintf(&str[2+15-i*3],(time_str[i]>=16)?"%x-":"0%x-",time_str[i]);
	str[10]=' ';
	str[13]=':';
	str[16]=':';
	str[19]=' ';
	str[20]=0;
	init_disp_nocls();//每秒都对显示器初始化一次
	str_hz(row,0,str);
}
//对网络cpu操作前的准备
void net_bgn(void)
{
	DDRA=0;
	PORTA=0x0;
	PORTB|=NCPU_BUSY;
	PORTE|=RD_WR;
	PORTC=ctl_data;
	PORTE|=ALE2;
}
//对网络cpu操作结束后恢复常态
void net_end(void)
{
	PORTC=ctl_data;
	PORTE&=~ALE2;
	PORTE&=~RD_WR;
}
//等待握手信号为0
byte wait_0_hs(void)
{
	word i;
	byte a;

	i=ms_count;
	for(;;)
	{
		if((ms_count-i)>2)
			break;
		PORTC&=~NCPU1_CE;
		PORTC|=NCPU1_CE;
		a=PINA;
		if((a&1)==0)//读忙状态
			return 0;
	}
	return 1;
}
//从网络cpu读
byte net_read(void)
{
	byte ndata;

	if(wait_0_hs())
		return 0xff;
	 
	PORTB&=~NCPU_BUSY;
	PORTC&=~NCPU1_CE;
	PORTC|=NCPU1_CE;
	ndata=PINA;
	PORTB|=NCPU_BUSY;
	return ndata;
}
//对网络cpu写
void net_write(byte ndata)
{
	if(wait_0_hs())
		ndata=0;

	DDRA=0xff;
	PORTB&=~NCPU_BUSY;
	PORTA=ndata;
	PORTE&=~RD_WR;
	PORTC&=~NCPU1_CE;
	PORTC|=NCPU1_CE;
	PORTE|=RD_WR;
	PORTB|=NCPU_BUSY;
	DDRA=0;
}
//等待握手信号为0
byte wait_0_hs_rst(void)
{
	word i;
	byte a;

	i=ms_count;
	for(;;)
	{
		if((ms_count-i)>200)
			break;
		PORTC&=~NCPU1_CE;
		PORTC|=NCPU1_CE;
		a=PINA;
		if((a&1)==0)//读忙状态
			return 0;
	}
	return 0;
}
//初始化网络cpu
void init_net(void)
{
	net_bgn();
	wait_0_hs_rst();
	net_write(CMD_NULL);	//传令牌
	wait_0_hs_rst();
	net_write(CMD_NULL);	//传令牌
	net_end();
}
//网络cpu复位
void net_rst(void)
{
	net_bgn();
	PORTC&=~NCPU_RST;
	mstimer1=10;
	while(mstimer1);
	PORTC|=NCPU_RST;
	mstimer1=690;
	while(mstimer1);
	wait_0_hs_rst();
	net_write(CMD_NULL);	//传令牌
	wait_0_hs_rst();
	net_write(CMD_NULL);	//传令牌
	net_end();
}

//在中断中接收串口数据
void rcv_int(void)
{
	if(USR&0x80)
	{
		commu_buf[com_i]=UDR;
		com_i++;
		if(com_i>=commu_end)
			poll_com=2;
		else
			mstimer3=50;//计数器置50ms
	}
	else
	if(mstimer3==0)
	{
		if((comm_timer==0)||(com_i!=0))
		{
			comm_timer=0;
			poll_com=2;
		}
		else
		{
			mstimer3=100;//重值计数器100ms
			if(com_c_key!=0)
				UDR=com_c_key;
		}
	}
}
//等待输出缓冲区空
void wait_com_empt(void)
{
	mstimer3=10;
	for(;mstimer3;comm_with_lon())
		if(USR&0x20)
			break;
}
//启动中断取数
void poll_rcv(byte c_key)
{
	if(poll_com!=0)
		return;
	if(c_key==0xff)
		com_c_key=0;
	else
	{
		com_c_key=CPU_ID|c_key;
		if(USR&0x80)//如果串口输入缓冲区中有数,则取出废掉
			com_i=UDR;
	}
	com_i=0;
	commu_end=(word)&commu_end-(word)commu_buf-2;//计算通讯缓冲区的长度
	if(com_c_key!=0)
	{
		wait_com_empt();
		for(;;)//等待输出缓冲区空
			if(USR&0x20)
				break;
		UDR=com_c_key;
	}
	mstimer3=100;
	poll_com=1;
}
//向串口发命令取数,如果命令是0xff,表示不发命令只取数,返回值是收数的长度
word com_rcv(byte c_key)
{
	poll_com=0;
	poll_rcv(c_key);
	for(;poll_com==1;)
		comm_with_lon();
	poll_com=0;
	return com_i;
}
//下发一个字节
void com_byte(byte c_key)
{
	wait_com_empt();
	UDR=c_key;
}
//下传多个字节
void com_snd(byte *str,word num)
{
	word i;
	for(i=0;i<num;i++)
	{
		wait_com_empt();
		UDR=str[i];
	}
}
//数据拷贝函数,对EEPROM指针特殊处理,大于等于0x4000的指针以EEPROM指针处理
void memcpy_e(byte *d,byte *s,byte num)
{
	if((((word)s)>=0x4000)&&(((word)d)>=0x4000))
		for(d=(byte *)((word)d&0x3fff),s=(byte *)((word)s&0x3fff);num;num--)
			EEPROMwrite((word)d++,EEPROMread((word)s++));
	else
	if(((word)s)>=0x4000)
		for(s=(byte *)((word)s&0x3fff);num;num--)
			*d++=EEPROMread((word)s++);
	else
	if(((word)d)>=0x4000)
		for(d=(byte *)((word)d&0x3fff);num;num--)
			EEPROMwrite((word)d++,*s++);
	else
		for(;num;num--)
			*d++=*s++;

}
//应用程序复位
void application_restart(void)
{
	asm("cli");			//关中断
	while(1)//过一会儿cpu内部看门狗动作
		comm_with_lon();
}
//光标定位及形状选择
void set_cursor_position(byte row,byte col,const byte *p)
{
	word lram;
	byte i,j;

	if(p==menucursor)
		j=32;
	else
		j=1;

	if(last_cursor)
	{//擦除老光标
		for(i=0;i<j;i++)
		{
			disp_order_data(0x0a,(byte)last_cursor);
			disp_order_data(0x0b,(byte)(last_cursor/256));
			disp_order(0x0c);
			disp_data(0x00);
			if(p==menucursor)
				disp_data(0x00);
			last_cursor+=20;
			i++;
		}
	}
	lram=row;
	lram=lram*20+col;
	last_cursor=lram;
	for(i=0;i<j;i++)
	{
		disp_order_data(0x0a,(byte)lram);
		disp_order_data(0x0b,(byte)(lram/256));
		disp_order(0x0c);
		if(p==menucursor)
			disp_data(p[i]);
		else
			disp_data(0xff);

		if(p==menucursor)
			disp_data(p[i+1]);
		lram+=20;
		i++;
	}
}
//显示函数
void LCD_display(byte j,byte k)
{
	cls();
	str_hz(j,k,disp_buffer);
}
//查表子程序,在二维表中查找要找的代码串,查到了则返回代码串在表中的位置
int FindString(const DaiMa *Table,char *ss)
{
	int i;

	for (i=0;;i++)
	{
		if(Table[i].AscCode==0)
			break;//二维表结束
		if(cstrcmp(Table[i].AscCode,ss)==0)
			return i;
	}
	return -1;
}
//******************************************************************
//垃圾程序,用来调整程序中全部的字符串的长度和程序的长度
void rubbish_s(void)//
{
	csprintf(disp_buffer,"fbjk");
//以上是调整字符串的长度
	PORTB|=WDG;
	PORTB|=WDG;
	PORTB|=WDG;
	PORTB|=WDG;
//以上是程序的长度
}

⌨️ 快捷键说明

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