||
C语言开发,我们这个行业还专门有人将单片机的C语言开发,甚至51单片机的c语言开发单独拿出来讲。搞得我刚入行的时候,以为那是一种特殊的C语言。甚至比英伟达GPU上那种开发语言还要距离“真正”的C语言更远......[/code]
一个从单片机开始的开发者
学校学的是电子专业,但是做硬件需要耐心和细心,几次电路板设计的失误让我彻底放弃了硬件这块儿。感觉还是软件更合适,学校只学了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代码跑在单片机上。