本帖最后由 keer_zu 于 2020-4-29 13:26 编辑
@Cjy_JDxy
C语言开发,我们这个行业还专门有人将单片机的C语言开发,甚至51单片机的c语言开发单独拿出来讲。搞得我刚入行的时候,以为那是一种特殊的C语言。甚至比英伟达GPU上那种开发语言还要距离“真正”的C语言更远......
一个从单片机开始的开发者
学校学的是电子专业,但是做硬件需要耐心和细心,几次电路板设计的失误让我彻底放弃了硬件这块儿。感觉还是软件更合适,学校只学了basic,于是自己学习了C语言的开发,那个时候感觉C语言好难,做pc下的c语言开发,如果涉及到底层,是非常牛X的事情,足以让人望而却步。也没有钱专门去做这方面的培训,于是就从单片机入手。
再贴一下自己第一段跑在单片机上的代码:
void text(void)
{
bit Flag_add; /*加一标志*/
bit Flag_sub; /*减一标志*/
unsigned char max_value; /*各时间单位的最大值*/
unsigned char min_value; /*各时间单位的最小值*/
/*if(FUN==1)
{ */ /*定义标志位*/
if(switch_work==0) /*移位键*/
{
if(Shift_on==0)
{
Shift_on=1;
buzzer();
clk_number++;
if(clk_number>6)clk_number=1;
}
}
else
Shift_on=0;
if(switch_up==0) /*加一键*/
{
if(Add_on==0)
{
Add_on=1;
buzzer();
Flag_add=1;
}
}
else
Add_on=0;
if(switch_down==0) /*减一键*/
{
if(Sub_on==0)
{
Sub_on=1;
buzzer();
Flag_sub=1;
}
}
else
Sub_on=0;
switch(clk_number)
{
case 1: max_value=99;min_value=0;break;
case 2: max_value=12;min_value=1;break;
case 3: if(clk_data[1]==1||
clk_data[1]==3||
clk_data[1]==5||
clk_data[1]==7||
clk_data[1]==8||
clk_data[1]==10||
clk_data[1]==12)
max_value=31; /*1,3,5,7,8,10,12*/
else if(
clk_data[1]==4||
clk_data[1]==6||
clk_data[1]==9||
clk_data[1]==11)
max_value=30; /*4,6,9,11*/
else if((clk_data[0]%4==0)||clk_data[0]==0)
max_value=29; /*闰年*/
else
max_value=28;
min_value=1;
break;
case 4: max_value=23;min_value=0;break;
case 5: max_value=59;min_value=0;break;
case 6: max_value=7;min_value=1;break;
}
if(Flag_add==1)
{
clk_data[clk_number-1]++;
Flag_add=0;
if(clk_data[clk_number-1]>max_value)
clk_data[clk_number-1]=min_value;
}
else if(Flag_sub==1)
{
clk_data[clk_number-1]--;
Flag_sub=0;
if(clk_data[clk_number-1]<min_value||clk_data[clk_number-1]==0xff)
clk_data[clk_number-1]=max_value;
}
if(switch_function==0)
{
if(function_on==0)
{
function_on=1;
FUN=0;
buzzer();
function_state=1;
fun0_flag=1;
set_time[0]=(clk_data[4]/10)*0x10+(clk_data[4]%10);
set_time[1]=(clk_data[3]/10)*0x10+(clk_data[3]%10);
set_time[2]=(clk_data[2]/10)*0x10+(clk_data[2]%10);
set_time[3]=(clk_data[1]/10)*0x10+(clk_data[1]%10);
set_time[4]=(clk_data[5]/10)*0x10+(clk_data[5]%10);
set_time[5]=(clk_data[0]/10)*0x10+(clk_data[0]%10);
}
}
else
{
function_on=0;
}
}
这段代码是运行在51单片机上的处女作,那是14年前的事情了。
当初从单片机开始接触编程,总觉得在linux(或者windows)上做开发好高大上。后来从学习安装linux和基本指令开始,直到在郑州一家做电力系统信息化的小公司接手一个之前时工做的linux项目维护开始(这里非常感谢时工的指点和帮助),后来工作中慢慢熟悉了linux应用开发。到上海后,抽空看看内核和驱动,在后边的工作中陆续用上了,感觉也就那样子吧。这个过程大概持续了四五年,大约14年之后就很少再关注linux的细节了,开始关注软件工程,敏捷开发,面向对象什么的,直到现在还是感觉自己在这方面所知甚少,没有达到设计一款软件时候有非常明确方向,并且有非常有效的手段的感觉,还是一些经验的积累,距离目标甚远。
最近的工作需要解决一些linux内核的问题,也会涉及到bootloader,没有什么特别的地方,方向也很明确,只是花点时间去理解一下linux某种特定机制而已:比如3.0之后内核增加的设备树概念,比如从android带来的低功耗管理等等。
linux的问题是一个理解别人做了什么,怎么做的问题。是一个相对很有边界的问题。
但是软件设计本身是一个在不断演进的问题,是一个没有边界的问题,而且很抽象,所以我一直更多花心思在这上面。
这些年,行业的热点在不停变换,所使用的技术也是不断演进,然而就相对底层的开发而言,变化就小很多。总有某些内容会沉淀下来的,他们需要花费很大的专注和领悟才能达到某种高度,要想有所成就就必须抛弃浮躁,但是这个行业本身又是那样浮躁,真不是一件容易做到的事情,而且做到了也常常看不到效果或者感觉付出没有得到应有的“回报”,取舍总是有的,生活中处处都是。
一个真正的软件工程师应该不能对平台依赖太多,而且尽量不要太依赖某一两种语言。
有很多事和平台无关的知识,也和语言无关。我们就是要在合适的平台上,用合适的语言去构建用户需要的系统。这个系统要兼顾可扩展(根据需要对某些内容方便扩展)和可维护性。有时候要根据具体情况对付出和收益作出权衡。
最近也抽空写一个可以在单片机和linux下都可以使用的简易通信框架:
zxcom
这里是其中一个文件pacet.c:
#include "packet.h"
#include "command.h"
#include "ucomlib.h"
unsigned int g_cur_msgid = 0;
static inline unsigned int get_new_msgid()
{
ENTER_CRITICAL();
if(g_cur_msgid >= 0x00ffffff){
g_cur_msgid = 0;
} else {
g_cur_msgid += 1;
}
EXIT_CRITICAL();
return g_cur_msgid;
}
int ZxcomOnPacket(const char *pack,const int len)
{
int ret;
unsigned int datalen;
char req[100];
handler_param_t param;
packet_t *packet = (packet_t *)pack;
unsigned int dir = GET_DIR(packet->ctrlInfo);
unsigned int msg_type = GET_MSG_TYPE(packet->ctrlInfo);
cmd_content_t *content = (cmd_content_t *)packet->data;
unsigned int msg_id = (unsigned int)GET_MSG_ID(packet->ctrlInfo);
if(dir == DIR_REQUEST) {
command_handler_t handler = g_command_manager.get_command(content->cmd_id);
if(handler == NULL){
return ERR_CMD_NOT_EXIST;
}
ret = handler(packet->data);
if(ret != 0) {
}
} else if(dir == DIR_RESPONSE) {
if(msg_type == MSG_TYPE_ASYNC) {
ret = CommGetMsg(msg_id,req,&datalen);
if(ret != 0) {
return ret;
}
packet_t *pk = (packet_t *)req;
cmd_content_t *cmd = (cmd_content_t *)pk->data;
param.req = cmd->param;
param.res = packet->data + sizeof(COMMAND_ID_TYPE);
command_handler_t handler = g_command_manager.get_response(content->cmd_id);
if(handler == NULL){
return ERR_CMD_NOT_EXIST;
}
ret = handler(¶m);
if(ret != 0) {
}
}
}
return 0;
}
int ZxcomOnSendMsg(COMMAND_ID_TYPE cmdId,const char *param,const unsigned int paramLen,char *packet)
{
int i,ret;
packet_t *pk = (packet_t *)packet;
unsigned int msgid = get_new_msgid();
pk->ctrlInfo = SET_CTRL_INFO(DIR_REQUEST, MSG_TYPE_ASYNC,msgid);
cmd_content_t *cmd = (cmd_content_t *)pk->data;
cmd->cmd_id = cmdId;
for(i = 0;i < paramLen;i ++) {
cmd->param[i] = param[i];
}
ret = CommSaveMsg(msgid,packet,paramLen + sizeof(COMMAND_ID_TYPE));
if(ret != 0) {
return ret;
}
return 0;
}
int ZxcomOnSendResponse(const void *recv,const char *param,const unsigned int paramLen,char *packet)
{
int i,ret;
const char *__mptr = (char *)recv;
packet_t *recv_pk = (packet_t *)(__mptr - offsetof(packet_t,data));
cmd_content_t *recv_content = (cmd_content_t *)recv_pk->data;
packet_t *pk = (packet_t *)packet;
pk->ctrlInfo = SET_CTRL_INFO(DIR_RESPONSE, MSG_TYPE_ASYNC,GET_MSG_ID(recv_pk->ctrlInfo));
cmd_content_t *content = (cmd_content_t *)pk->data;
content->cmd_id = recv_content->cmd_id;
for(i = 0;i < paramLen;i ++) {
content->param[i] = param[i];
}
return 0;
}
希望有人可以把这些C代码跑在单片机上。
|
@hobbye501 :术业有专攻。再说了,自从硬件集成度越来越高,很多硬件岗位就集中在少数大公司了。
时代在进步 效率在提高 越来越多的 库啊 操作系统啊 等等进入我们的世界 大大提高了“外包”的开发成本,硬件关心的人是 越来越少了