51单片机很麻烦

在IO口不够用情况下可以考虑的:

11.网络芯片w5500是单片机网络的福音。但一个连接就需要4k内存。

1. 输入使用矩阵按键,参考8点。 如果使用ADC做按键输入,可以参考STC中的"ADC做按键扫描应用线路图"; 并口转串口可用74HC165实现联级使用

2. 输出可以使用联级74HC595来处理,IO口只需要3个。一个74HC595可控制8个输出口,然后就是看成本了!

3. 对于断码屏控制,使用的是ht1621系列!

4. STC可以考虑:STC8G2K64S4(ram2k,code64,adc10位,48脚,参考价2.2元) ; STC8A8K64S4A12(ram8k,code64k,adc12位,64脚,参考价3.4元,可能是货少,比较贵);内部时钟可以到35M,在64K以下STM32可以考虑用他们!

STC8A8K64D4

5. 做usb设备可以用CH375(价格高)。串口转usb:HT42B534

6. WT588F02B语音芯片可以播放254段语音(便宜1-2块)。SYN6288E是TTS语音模块,可以输出自定义语音(10多块)。

7. STC带IAP功能的,可以参考数据手册附录I(stc8a):需要64k空间全部配置为EEPROM,再自己分配IAP区启动区,AP区应用区,参数区。

必须参考STC官方指导文档:"利用宏晶科技的IAP单片机开发自己的ISP程序.pdf"。必须如0-50K是APP,后面51-60K是引导程序,60-63K参数等。

引导程序不开中断,是主程序来做串口接收发送。

软件复位单片机,看门狗继续工作,因此引导程序需要喂狗!

官网参考:百度网盘 请输入提取码

q4uj

8. 按键矩阵个人看法,此想法以实际验证通过:

电路可参考:

(网上大多都是只能判断1个按键被按下)为了实现检测同时按多按键,把第一行输出1,其他行与列都设置为高阻输入(P0M0与P0M1配置),这样这些输入口不会干扰检测电路,这样检测1-4列输入,可以判断1-4按钮是否按下。以此类推检测出5-8,9-12,13-16。

9. 74HC94驱动程序,网上的代码有bug。我这里用5个74HC595

sbit P_HC595_DATA = P3 ^ 4;   //SER                data input
sbit P_HC595_LATCH = P2 ^ 0;  // RCLk        store (latch) clock
sbit P_HC595_CLK = P2 ^ 1; //SRCLK        Shift data clock
#define PRIDORM_MAX_LED 40
u8 xdata stc595LastBuf[PRIDORM_MAX_LED / 8] = {0};
u8 xdata tmp595buf[PRIDORM_MAX_LED / 8] = {0};
//工作状态:0灭,1亮,2闪。
u8 xdata stdLedWorkBuf[PRIDORM_MAX_LED / 4] = {0};

//级联工作https://blog.csdn.net/sheeptech/article/details/82697090
//5个74hc595串联使用没有问题!
void stc74hc595SndData(u8 *OutData, int len)
{
    u8 i, j, tmpDataVal;
    P_HC595_LATCH = 0;//网上代码有问题,必须在前
    for (i = 0; i < len; i++)
    {
        tmpDataVal = OutData[len - 1 - i];
        for(j = 0; j < 8; j++)
        {
            P_HC595_CLK = 0;//网上代码有问题,必须在前
            if ((tmpDataVal & 0x80) == 0x80)
            {
                P_HC595_DATA = 1;
            }
            else
            {
                P_HC595_DATA = 0;
            }
            tmpDataVal = tmpDataVal << 1;
            P_HC595_CLK = 1;
        }
    }
    P_HC595_LATCH = 1;
}
 

10. 用编译时间做版本号:

#define STC_WORK_MASTOR_VERSION 7878ul//0-8191
char code mouthBuf[][4] = {
	"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};
u32 versionStrToVerVal(void)
{
	int i;
	u32 m = 13,d = 0,y = 0;
	int flag;
	const char *verbuf;
	int verlen;
	verbuf = __DATE__;
	verlen = strlen(__DATE__);
	for(i = 0; i < 12; i++)
	{
		if(verbuf[0] == mouthBuf[i][0] && verbuf[1] == mouthBuf[i][1] && verbuf[2] == mouthBuf[i][2])
		{
			m = i+1;
			break;
		}
	}
	if(m == 13)
	{
		return 0;
	}
	for(i = 0; i < verlen; i++)
	{
		if(verbuf[i] == ' ')
		{
			if(flag == 2)
			{
				break;
			}
			flag = 1;
		}
		else if(flag != 0 && (verbuf[i] >= '0' && verbuf[i] <= '9'))
		{
			d *= 10;
			d += (verbuf[i] - '0');
			flag = 2;
		}
	}
	for(;i < verlen; i++)
	{
		if(verbuf[i] >= '0' && verbuf[i] <= '9')
		{
			y *= 10;
			y += (verbuf[i] - '0');
		}
	}
	stcWorkVersion = (STC_WORK_MASTOR_VERSION << 19) + ((y % 1000) << 9) + (m << 5) + d;
    memset(heartbeatBuf, 0, sizeof(heartbeatBuf));
    memset(heartRcvBuf, 0, sizeof(heartRcvBuf));
	heartbeatBuf[0] = (u8)(stcWorkVersion >> 24);
	heartbeatBuf[1] = (u8)(stcWorkVersion >> 16);
	heartbeatBuf[2] = (u8)(stcWorkVersion >> 8);
	heartbeatBuf[3] = (u8)(stcWorkVersion >> 0);
	return stcWorkVersion;
}

使用C51比较头痛的问题:我使用了KEIL3,KEILC51-9.60,他们的STDIO.H是一样的,所以C51都不能逃离这些问题!

------>C51使用函数指针,经常出现数据不正常。我直接放弃使用函数指针。备注:在STM32能正常运行的函数指针程序。

------>寄存器不能连续操作两次,否则第一次不会成功。

P2M1 &= ~(0x3f << 2);
P2M1 |= (0x11 << 2);
其中第一句不成功。
通过下面方式来弥补:
extern u8 xdata stcRegistorSetVal;
#define setValBits(chval, shift, mask, bitsval)                   \
    {                                                             \
        stcRegistorSetVal = (chval);                                \
        (stcRegistorSetVal) &= ~((mask) << (shift));              \
        (stcRegistorSetVal) |= (((bitsval) & (mask)) << (shift)); \
        (chval) = stcRegistorSetVal;                                \
    }
使用参考:
setValBits(P2M1, 2, 0x3f, 0x11);

------>为了管控时间,做一个1ms定时器。结果主程序使用trunclk时出现错误,加了volatile也一样,0xff + 1后不是0x100,而是0x00,导致出错!故tnowms用下面的方式来修补!

#include "stcTimer.h"
#define TIMER0_FREQ_CLK (65536 - STC_WORK_SYSCLK / 12 / 1000)//1000hz的定时器,1ms
static volatile u32 xdata trunclk = 0;
static u32 xdata tmpclk = 0, tmpclk1 = 0;
void timer0_Isr() interrupt 1
{
    trunclk++;
}

void timerWorkInit(void)
{
    //TMOD = 0x00;//模式0
    TL0 = TIMER0_FREQ_CLK;                                 //65536-11.0592M/12/1000
    TH0 = TIMER0_FREQ_CLK >> 8;
    TR0 = 1;                                    //启动定时器
    ET0 = 1;                                    //使能定时器中断
}

u32 tnowms()
{
    tmpclk = trunclk;
    if((tmpclk & 0x000000ff) == 0x00)
    {
        return tmpclk1;
    }
    else
    {
        tmpclk1 = tmpclk;
        return tmpclk1;
    }
}

// void tmdelay(u32 tms)
// {
//     u32 nowm = tnowms();
//     while(tnowms() - nowm < tms)
//     {
//         ;
//     }
//     return;
// }

----->中断调用函数a,其他中断或主函数也调用函数a,就会报错:

WARNING L15: MULTIPLE CALL TO SEGMENT

做两个功能相同的函数,函数名不同,分别调用即可。这跟优化有关,如果优化为0,不会出这个问题。

--->STC8A8K64D4我配置成45M,结果EEPROM写入不成功,配成35M可以!

---->STC中的SRAM大小等于256字节idata内部RAM+xdata大小。xdata变量长度>SRAM-idata长度,会导致程序跑不起来。

printf在 stc中需要注意的:

1. 不能识别宏定义中的...:printfdbg(a, ...),没有库函数vsnprintf

2. %d不能正常打印u8类型数据,%d使用(u16)强制转换一下printdbgUart1("[%s,%d]val3=0x%x\r\n", __FILE__, (u16)__LINE__, (u16)0x1234);

3. %f在一个printf中不能出现2次!不能打印.3f格式!

4. %lu不能出现两次

5. 定义数据为code,不占xdata空间,如果定义为const就要占xdata空间。如果xdata空间大于STC规定的大小,程序将会异常,请熟知!

void printdbgUart1(char *format, ...)
{
    int i = 0;
    va_list vArgList;
    va_start(vArgList, format);
    vsprintf(comTmpStrUser, format, vArgList);
    va_end(vArgList);
    uart1SendString(comTmpStrUser, strlen(comTmpStrUser));
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
51单片机是一种较为常见的单片机型号,采用C语言进行编程。以下是关于51单片机C语言编程的一些相关内容。 首先,51单片机C语言编程需要具备一定的C语言基础知识。因为C语言是一种较为通用的编程语言,掌握好基本的数据类型、语法、流程控制等知识对于编写51单片机的程序非常重要。 其次,编写51单片机的程序需要用到C语言的标准库函数以及51单片机特定的功能库函数。标准库函数可以帮助我们实现一些基本的功能,如输入输出、字符串处理等。而51单片机特定的功能库函数则包括了与51单片机硬件相关的操作,比如计时器、中断等。 另外,编程过程中还需要了解51单片机的内部结构和寄存器的使用方法。了解51单片机的内部结构和寄存器的功能可以帮助我们更好地控制硬件,编写出更为高效的程序。 最后,对于51单片机C语言编程来说,还需要有一定的电路基础知识。因为51单片机是一种嵌入式系统,需要和外部电路进行配合使用。了解一些电路知识可以帮助我们更好地理解51单片机的工作原理,并且在实际应用中进行硬件设计和调试。 总之,51单片机C语言编程是一门综合性比较强的技术,除了掌握C语言的基础知识外,还需要了解51单片机的内部结构和硬件特性,并且具备一定的电路基础知识。只有综合运用这些知识,我们才能够编写出高效、可靠的51单片机程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值