做硬件的是不是都不会写代码啊?

近来闲着没事儿干,仿制了杜洋的DIY18一位数字时钟。我是照着书做的,网页在这里:

http://doyoung.net/works/One_Bit_Digital_Clock/index.html

搞定之后,回过头来看看代码。不看不要紧,一看差点把鼻子气歪了。这代码的质量这叫一个差,杜洋同学你写程序是不是体育老师教的啊?程序写成这样还好意思整天写书教别人吗?还好意思整天变着法骗初学者的钱吗?没办法,哥们我重写了一遍,贴出来给大伙瞧瞧,什么叫有质量的代码。

哥的代码,解决了原来杜洋写的代码的这些问题:

1. 原来的代码又臭又长,充斥了大量的类似语句罗列不说,.hex要占用1418字节ROM。就算改成最强的优化模式,也要占1315个字节。我的代码只需要1007个字节。节省了20%以上的ROM空间,可以用1K ROM的STC12C1052存下了,哈哈。

2. 原来的代码逻辑、数据混杂在一起,维护、扩展困难。我写的代码,把显示的行为作为数据单独列出来,和控制逻辑完全分离。这是我的代码的最重要的改进。这样,没有了冗长的代码,想进一步扩展功能也很容易,还顺带解决了下面说的用户交互体验问题。

3. 原来的代码用户交互体验很差。从代码里面就可以看出来,很长的一个行为完成之后,才检测一次按键是否被按下了。这样,想调整一下时间,得按key1按好久。很明显杜洋同学也意识到这是一个问题,还专门做个一个小交互,key1按键被程序响应,会以点亮G1/G2,显示"-"作为反馈。但你不觉得这样好傻吗?在我的代码中,逻辑和数据分离,把显示行为分为一个一个细小的步骤进行,因此按键可以以非常快的速度被程序响应。妈妈再也不用担心按下按键没反应啦。

这么一点点代码,就有这么多的问题,可见做硬件的同学真是不会写代码啊,哈哈哈哈。下面是哥的代码,小朋友们都学着点。

#include <reg51.h> //MCS-51 Í·Îļþ   
#include <intrins.h>   

sbit key1 = P1 ^ 4;
sbit key2 = P1 ^ 3;
bit key1_current;
bit key2_current;

unsigned char data tick  = 0;				// ¶Ô10msʱ»ùÐźÅÀÛ¼Óµ½1s
unsigned char data sec = 0;					// Ãë¼ÆÊýÆ÷(00s-59s)
unsigned char data min_high = 0;		// ·Ö¼ÆÊýÆ÷(00m-59m)
unsigned char data min_low = 1;
unsigned char data hour_high = 0;		// ʱ¼ÆÊýÆ÷(00h-23h)
unsigned char data hour_low = 2;

void timer0(void) interrupt 1				// T/C0ÖжϷþÎñ³ÌÐò(²úÉú10msʱ»ùÐźÅ)
{
	tick++;
	if(tick >= 100)
	{
		tick = 0;
		sec++;
		if(sec >= 60)
		{
			sec = 0;
			min_low++;
			if(min_low >= 10)
			{
				min_low = 0;
				min_high++;
				if (min_high >= 6)
				{
					min_high = 0;
					hour_low++;
					if (hour_low >= 10)
					{
						hour_low = 0;
						hour_high++;
						if (hour_high * 10 + hour_low >= 24)
						{
							hour_high = 0;
							hour_low = 0;
						}
					}
				}
			}
		}
	}
	// ÖØÖö¨Ê±³£Êý   
	TH0 = 0xd8;
	TL0 = 0xf0;   
}

// Each byte represents an action. An action series end up with 0x00 is a step.
// bit 7    : SFR register, 0 for P1, 1 for P3.
// bit 4 ~ 6: SFR bit to be switched.
// bit 3    : LED on/off (inv).
// bit 0 ~ 1: Action type,
//            1 for just do the LED switch,
//            2 for pause 1 unit after LED switch,
//            3 for no LED switch and pause unit * (bit 2 ~ 8) up to 945ms (when pause_unit is 150).

code unsigned char cc_0[] = {0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0x02, 0x12, 0x32, 0x42, 0x00};
code unsigned char cc_1[] = {0x12, 0x02, 0xD2, 0xC2, 0x00};
code unsigned char cc_2[] = {0x42, 0x32, 0x12, 0x02, 0x22, 0x52, 0x82, 0x92, 0xA2, 0xB2, 0x00};
code unsigned char cc_3[] = {0x42, 0x32, 0x12, 0x02, 0x52, 0x22, 0xD2, 0xC2, 0xB2, 0xA2, 0x00};
code unsigned char cc_4[] = {0x62, 0x72, 0x52, 0x22, 0x12, 0x02, 0xD2, 0xC2, 0x00};
code unsigned char cc_5[] = {0x32, 0x42, 0x62, 0x72, 0x52, 0x22, 0xD2, 0xC2, 0xB2, 0xA2, 0x00};
code unsigned char cc_6[] = {0x32, 0x42, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0x22, 0x52, 0x00};
code unsigned char cc_7[] = {0x42, 0x32, 0x12, 0x02, 0xD2, 0xC2, 0x00};
code unsigned char cc_8[] = {0x02, 0x12, 0x32, 0x42, 0x62, 0x72, 0x52, 0x22, 0xD2, 0xC2, 0xB2, 0xA2, 0x92, 0x82, 0x00};
code unsigned char cc_9[] = {0x02, 0x12, 0x32, 0x42, 0x62, 0x72, 0x52, 0x22, 0xD2, 0xC2, 0xB2, 0xA2, 0x00};
code unsigned char code *cc_number[] = {cc_0, cc_1, cc_2, cc_3, cc_4, cc_5, cc_6, cc_7, cc_8, cc_9};

code unsigned char cc_clear[] = 
	{0x33, 0xCA, 0xBA, 0xDA, 0xAA, 0x9A, 0x2A, 0x8A, 0x5A, 0x0A, 0x1A, 0x7A, 0x3A, 0x6A, 0x4A, 0x2F, 0x00};
code unsigned char cc_colon[] = 
	{0x01, 0xC2, 0x4B, 0x09, 0xCA, 0x2F, 0x00};
code unsigned char cc_pause[] = 
	{0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x00};

unsigned char code *step[10] = 
	{cc_clear, cc_pause, cc_0, cc_clear, cc_0, cc_clear, cc_colon, cc_0, cc_clear, cc_0};

unsigned char data mode = 0;
unsigned char data mode_steps = 10;
unsigned char data current_step = 0;
unsigned char data current_action = 0;
unsigned char data pause_unit = 150;

unsigned char data p1_backup = 0xff;  // Backup output value

// ÑÓʱº¯Êý
void delay(unsigned int a)
{
	unsigned char i;
	while( --a != 0){		
		for(i = 0; i < 125; i++)
		;
	}   				   
}

void doAction(char action)
{
	unsigned char action_type = action & 0x03;
	unsigned char i;
	if (action_type == 3)
	{
		unsigned char pausecount = action >> 2;
		for (i = 0; i < pausecount; ++i)
		{
			delay(pause_unit);
		}
	}
	else
	{
		unsigned char led_sfr = action & 0x80;
		unsigned char led_bit = (action & 0x70) >> 4;
		unsigned char led_bitmask = 1 << led_bit;
		unsigned char onoff_inv = action & 0x08;
		
		if (onoff_inv != 0)
		{
			// off
			if (led_sfr == 0)
			{
				p1_backup |= led_bitmask;
				P1 = p1_backup;
			}
			else
			{
				P3 |= led_bitmask;
			}
		}
		else
		{
			// on
			if (led_sfr == 0)
			{
				p1_backup &= (~led_bitmask);
				P1 = p1_backup;
			}
			else
			{
				P3 &= (~led_bitmask);
			}
		}
		
		if (action_type == 2)
		{
			delay(pause_unit);
		}
	}
}

void doStep(void)
{
	char action;
	
	if (current_step == 0 && current_action == 0)
	{
		// Format time in step[] before each cycle
		if (mode == 0)
		{
			step[2] = cc_number[hour_high];
			step[4] = cc_number[hour_low];
			step[7] = cc_number[min_high];
			step[9] = cc_number[min_low];
		}
		else
		{
			if (mode == 1)
				step[2] = cc_number[hour_high];
			else if (mode == 2)
				step[2] = cc_number[hour_low];
			else if (mode == 3)
				step[2] = cc_number[min_high];
			else
				step[2] = cc_number[min_low];
		}
	}

	// Just do it!
	action = step[current_step][current_action++];
	if (action == 0x00)
	{
		current_action = 0;
		current_step++;
		if (current_step >= mode_steps)
		{
			current_step = 0;
		}
	}
	else
	{
		doAction(action);
	}
}

void adjustTime()
{
	switch (mode)
	{
	case 1:
		{
			hour_high++;
			if (hour_high > 2)
			{
				//Èç¹ûСʱʮλ´óÓÚ2ÔòÇå0
				hour_high = 0;
			}
		}
		break;
	
	case 2:
		{
			hour_low++;
			if (hour_high > 1 && hour_low > 3)
			{
				hour_low = 0;
			}
			else if (hour_low > 9)
			{
				hour_low = 0;
			}
		}
		break;
	
	case 3:
		{
			min_high++;
			if (min_high > 5)
			{
				min_high = 0;
			}
		}
		break;
	
	case 4:
		{
			min_low++;
			if (min_low > 9)
			{
				min_low = 0;
			}
			sec = 0;//µ÷ʱÍê³Éºó°ÑÃëÇå0
		}
		break;
	}
}

void getKeyStatus()
{
	// Turn off the LED
	key1 = 1;
	key2 = 1;
	
	// Get the keys 
	key1_current = key1;
	key2_current = key2;

	// Restore
	P1 = p1_backup;
}

void main(void)
{
	TMOD = 0x11;         // ¶¨Ê±/¼ÆÊýÆ÷0,1¹¤×÷ÓÚ·½Ê½1   
	TH0 = 0xd8;          // Ô¤Öö¨Ê±³£Êý55536(d8f0),²úÉú10msʱ»ùÐźŠ  
	TL0 = 0xf0;   
	EA = 1;              // ¿ª×ÜÖÐ¶Ï   
	ET0 = 1;             // ¶¨Ê±/¼ÆÊýÆ÷0ÔÊÐíÖÐ¶Ï   
	TR0 = 1;             // ¿ª±Õ¶¨Ê±/¼ÆÊýÆ÷0

	while (1)
	{
		getKeyStatus();
		
		if (key1_current == 0)
		{
			delay(50);
			getKeyStatus();
			if (key1_current == 0)
			{
				// Switch modes
				mode++;
				if (mode >= 5)
					mode = 0;
				
				current_action = 0;
				current_step = 0;
				
				if (mode == 0)
				{
					mode_steps = 10;
					step[3] = cc_clear;
					pause_unit = 150;
				}
				else
				{
					// clear, pause, number, pause
					mode_steps = 4;
					step[3] = cc_pause;
					pause_unit = 10;
				}
			}
		}
		
		if (key2_current == 0)
		{
			delay(50);
			getKeyStatus();
			if (key2_current == 0)
			{
				adjustTime();
			}
		}

		// µÈ´ý°´¼ü·Å¿ª
		while(key1_current == 0 || key2_current == 0)
		{
			getKeyStatus();
		}

		doStep();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值