<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post/9975/</link>
<title><![CDATA[[转]我是如何把一个项目带崩的，多么痛的领悟，做项目前值得多次阅读并深刻检查。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Wed, 05 Dec 2018 08:09:11 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/9975/</guid> 
<description>
<![CDATA[ 
	项目和团队背景<br/>首先给大家说明一下项目背景，以便各位对此项目有更清晰的了解：<br/>1.该项目是一个二次开发项目，第一个基础版本（打印申报系统）也由我带领开发。<br/>2.系统是需要和国家系统对接，有三条主流程。<br/>3.需求频繁变化，由于系统需要对接国家系统，需求方对需求也不甚了解。曾在5月份一个月内需求变更超过8次，都是主流程变更。<br/>4.项目大小按照最初需求估算，约在100人天左右。<br/>5.项目两条主流程无法测试，依赖于外部U盾，但开发过程中并没有U盾。<br/>6.客户现场使用U盾调试和开发时间约为20天左右。<br/>7.我当时同时负责大大小小4个项目，没有进入开发，仅管控进度。<br/>8.团队成员共3名，其中两名是当时开发基础版本的项目成员，他们对此项目较为熟悉。<br/>9.项目推进过程中，需要多次去现场调试测试，由团队中的两名工程师共同前去。<br/><br/>我做错了什么<br/>除了监控进度，还要管理质量<br/><br/>在项目的开发初期，我制定了一份详细的开发计划，用于指导整个开发过程。开发计划交付与了客户，而答应了的事情就要做到，所以在整个项目过程中，我对进度管控很严。我定期检查功能是否完成，定期和客户汇报情况，保证了开发进度顺利推进。但也由此埋下了祸根，仅仅看需求是否完成，而未关注完成的质量如何。<br/><br/>项目质量出现了许多细节性问题。比如：<br/>1.上线后，客户那边发现其中一条主流程都走不下去<br/>2.其中申报功能，系统提示成功。但实际上并没有真的申报成功，申报后在国家系统无法查询到<br/>3.打印功能小问题较多，打印获取的数据错误<br/>4.同步数据的功能无法同步或者同步的数据错误<br/>5.执行时间过长的功能，数据库会强制断开连接<br/>等等问题，就不一一列举<br/><br/>反思：<br/>1.进度和开发速度固然重要，但以质量换速度不可取<br/>2.如果开发时间和质量冲突，优先保质量，毕竟你埋下的坑，总是要坑你自己的<br/>3.再困难的情况下，也要保证基本测试<br/>4.时间极其不允许的情况下，也要保证主线功能顺利执行<br/><br/>既要给予信任，也要保持警惕<br/><br/>项目中的三名成员，都是合格的开发，对使用的框架非常熟悉。其中两名还是基础版本开发成员，对需求也很熟悉。所以项目中，我放心的把整个项目交给了他们。基于对他们的放心，加上其他项目事情繁杂，对此项目关注度，对他们的关注度就不够了。<br/><br/>我在项目中给予了他们非常充分的信任，信任他们可以把一切事情都做好。但我没有在正确的时候给予他们正确的指引，项目中出现的困难点，我也没有帮助他们解决，甚至于没有给出思路。所有的一切，都靠他们自己完成。我在这个项目里做的，就是对接客户，催进度。再无第三件事。<br/><br/>反思：<br/>1.不论什么原因，都要关注到项目成员的状态<br/>2.给予信任没错，但也要适当保持警惕，他们多少会因为经验问题疏忽遗漏一些问题<br/>3.给予信任，也要给予帮助，不以时间为理由推脱你应该对他们进行的指点和帮助。毕竟现在剩下来一分钟，以后要花一个小时去弥补<br/><br/>若无法全局掌控，就指派专人负责<br/><br/>这是我在项目中做的最错误的地方。<br/><br/>由于种种原因，我无法掌握到项目的每个要点和细节。而项目中有三个开发。我并没指明其中某一个来负责整个项目，所有事情都让他们自己商量。从客户对接来的问题，我也是仅告知对应的开发。整个项目中，没有一个人对项目中的每个要点了如指掌。<br/><br/>反思：<br/>1.手里捏着管理的权利，却没有做到管理的事情。是我在这个项目里最大的问题<br/>2.授权！授权！授权！如果自己无法亲力亲为投入项目管理工作，就授权给团队某个成员管理权限，让他代替你去做管理工作<br/>3.管理一人，总比管理多个人轻松，也更有效<br/><br/>要控制需求，更要控制流程<br/><br/>项目是二次开发、成员对项目很熟悉、项目工作量不大、时间紧。<br/><br/>基于以上原因，我掉以轻心，没有在项目初期进行项目的设计和规划，未指定任何开发规范。仅仅告诉开发的同事要多复用，也未检查他们是否真的复用了。<br/><br/>项目开发中的需求变更，客户反馈意见，我我都仅仅是告知他们一声，未做详细的修改规划，所有事情都靠嘴说，所有变动都放在了我和他们的脑子里。<br/><br/>对项目上心程度不够，未对客户的需求变更做控制和管理。所有变更都压给了开发的同事。<br/><br/>整个项目以及其不规范的方式在运行，我也未在其中起到控制作用，项目开发一团乱麻。<br/><br/>反思：<br/>1.不做设计，不进开发<br/>2.以管理工具指导开发进行，开发过程中所有变更、反馈做记录<br/>3.控制需求变更，拒绝不合理的需求<br/>4.需求变更规范化操作，统一变更，而不是直接压给开发<br/><br/>无论什么情况下，都要进行code review<br/><br/>整个项目过去了几乎四个月，我仅仅花了两个多小时简单看了下代码，未指出代码的任何问题。这也导致出问题后来我花了成倍的时间来处理code review的工作，并且项目成型后的代码修改困难。<br/><br/>项目开发过程中，也未让开发间互相进行代码review，也没有进行代码评审会。<br/><br/>其实代码中出现了很多问题，最后检查代码的时候，发现各种命名不规范、代码复用不到位、简单逻辑复杂写等等。而这些问题，很大一部分都是早期未做规定，未指定人负责项目、未进行早期code review造成的。开发各自为战，难免造成代码问题。<br/><br/>代码质量的问题，淋漓尽致的体现的在项目中，项目中的诸多bug，都是因为代码不规范引起的。甚至于开发人员自己对自己写过的东西，都有些拎不清了。<br/><br/>反思：<br/>1.代码质量非常重要，代码越规范bug越少<br/>2.代码互评能让开发更注重自己代码的质量<br/>3.code review非常有必要，越早期的code review越能有效的节省后期的时间<br/><br/>我在其中占有多重的因素<br/>100%<br/><br/>我怎么填坑的<br/>项目上线，问题频出，用户不满。花了8天时间来处理这个问题。幸亏项目不大，我一个人也能够挽回。<br/><br/>目前暂时解决完毕，我简单说一下我是怎么填坑的：<br/>1.和开发主流程的同事详细熟悉了所有需求要点<br/>2.基于我对项目需求的熟悉，我花了三天把所有主流程的所有代码分析完毕，做出了我认为应该的修改，并实施部署到生产环境测试（这是在给开着的飞机换引擎，但需要U盾才能测试，仅有生产环境的机器有U盾，别无他法）<br/>3.每天花超过12个小时来进行code review 和修改，几乎每天code review + 修改到凌晨2点多（仅修改了问题较大且影响较小的地方。小问题未修改、牵涉面较广的地方未修改）<br/>4.每次上班时间的修改让开发同事坐在旁边和我一起进行，我进行修改，开发同事在一旁监督。确保我不出错<br/>5.优化功能点，把我发现的提示问题，和优化点都同步修改进代码中，确保用户体验不要太糟，以期能挽回一些用户心态<br/><br/>我所吸取的教训总结<br/>1.先设计，后开发<br/>2.管理权下放，项目中必须有人全身心负责<br/>3.无论什么情况都要进行code review<br/>4.压缩质量得到的进度保证不可取，开发周期不合理决不答应客户。否则坑了自己坑了同事，更坑了客户<br/><br/>From:http://www.leidun.site/index.php?s=/forum/plate/topic/id/102.html&amp;from=groupmessage&amp;isappinstalled=0&amp;code=081IBpIS0UeVRY1AGDJS0HFmIS0IBpID&amp;state=STATE
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/9431/</link>
<title><![CDATA[高效、有效、实效]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Tue, 29 Aug 2017 01:56:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/9431/</guid> 
<description>
<![CDATA[ 
	高效、有效、实效
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6852/</link>
<title><![CDATA[《管理十戒》读书笔记之八戒。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Tue, 03 Dec 2013 05:59:12 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6852/</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp; 以前买了本书，一直没看，趁上个周末从纸箱里看了本叫《管理十诫》的书，结合自己经历过的环境还是颇有感触,尤其是对官僚作风的描述可堪称为金典，它就是管理十诫第八诫：<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;行政作风盛行，团队臃肿：作者刚刚从休斯敦到搬到亚特兰大的时候（刚从可口可乐分公司调任到可口可乐总部）发生在秘书身上的事情，也让我感到目前一些公司的官僚和制度化所带来的负面的影响。事情是这样的，作者的秘书在作者去总部上班之前，去总部帮助作者布置办公室，秘书被急哭了。为什么呢？因为他没有办法继续他的工作，因为即使要找一个简单的文具，也需要先填写申请单，然后由相关经手的人去处理，就为了布置办公室一连忙了很多天还无法进展下去。“如果你想让你一事无成，就让官僚主义盛行”。一个人所拥有的任何影响和权力都来自月他名片上方的职位，而不是他的名字。每个组织都有外人难以逾越的障碍。其实并不是作者的秘书周围的同事不够友好，在一个巨大的官僚机构里，人们永远都不会对你说不，但是你想要的东西，却不一定能够拿到。员工的离职其中一个很重要的原因并不是薪酬不够，而是他们在开展工作的时候收到掣肘。作为管理者最应该做的就是让你的员工能够顺顺利利的完成工作。<br/>——————————————————————————————————————————————————————<br/>“官僚”本意是指官员的办公室，而“主义”指的是规矩。<br/><br/>在现代社会中，如果没有官僚主义，就不可能支撑起这么井然有序的生活。但是，如同机械一样精妙的组织架构不应该成为阻碍个人发挥创造力和生产力的兰路虎。<br/><br/>个性，个人的创造力，个人感触，个人的情感投入，个人的想象力，这些都是开展每项工作不可或缺的品质，在整个组织中我们必须提供这些品质成长所需的沃土。<br/><br/>但，有时候恰恰相反，在每个公司中，为了使一起都变得井井有条，就必须有各式各样的规定和惯例。长此以往，规定和惯例在变成了冰冷，陈旧的条条框框，反而成了扼杀组织活力的绊脚石。而控制这些条条框框的人却死守着自己的一亩三分地，借助这些条条框框来维护自己的权威。这些官僚们整天表现出一副忙得昏天黑地的样子，但其实连一丁点的有创造性的工作都没有做。<br/><br/>必须要对那些尾大不掉，积习难改的臃肿公司进行大刀阔斧的精简改革。因为机构僵化的的官僚体制是很让人受挫的，这些官僚不但自己不作为，而且显然还阻碍其他人的进步。<br/><br/>唐纳德基奥坚信，只要公司的上上下下都有一个信念——推销自己公司的产品和品牌，那么公司肯定会经营的不错。这就是以销售为出发点的思考模式。公司的管理层的主要任务就是让各个部门之间能够尽快的配合顺利完成工作。<br/><br/>管理大师德鲁克说过，卓越的公司从来不会陷于微观管理，从来都不会让员工的每分每秒都有疲于奔命的感觉。尽量扁平化公司的内部结构，那些不涉及到公司利益的部门（比如后勤部门等）就可以外包给其他供应商，这样既提高效率，又不会浪费精力。<br/><br/>公司里的人才越多，那么官僚主义的决定要么就是把好点子扼杀了，要么就会体现一种从众心态。毕竟没有人愿意扫大家的兴。<br/><br/>公司的扁平化运作有助于提高效率，但同时也必须有一些规定来保证基本的工作秩序。所以，这之间的平衡关系要根据公司的规模制定。
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6779/</link>
<title><![CDATA[于刚自述：1号店怎样用3年把销售额从0元做到8亿]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Thu, 31 Oct 2013 06:59:37 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6779/</guid> 
<description>
<![CDATA[ 
	对系统定下几个标准，而这也成了我们做的最正确决策之一。<br/>　　第一个，系统必须集成化。我们不允许有各种各样独立的零散系统，所以可以看到现在一个系统里面有供应商、采购、仓储、配送、客服、价格、类目管理和营销管理等各种大小模块。这样就保证所有系统用的数据都是一样的，供应链和配送等各种信息也都是透明的。<br/>　　第二，系统一定要实时。我们一定要实时地看到所有资源的使用情况，这个要求比较高一点。<br/>　　第三，这个系统一定要是柔性的。它要允许我们不断地去尝试新的商务模式，允许做错的时候可以改。<br/>　　第四，这个系统一定要是可扩的。现在看起来，这个标准越来越发重要，因为当我们流量、销售、商品越来越多越来越大的时候，我们不需要改基础架构，只需增加模块和服务器就行了。<br/><br/><br/><br/>口述：于刚(黑马营导师、1号店董事长)<br/>　　整理：王根旺（创业家杂志驻黑马营记者）<br/>　　【导读】该文是1号店董事长于刚为黑马营六期学员做的近三个小时授课内容节选。5年里，于刚从职业经理人到创业者，从被前呼后拥到遭遇白眼，1号店从零做到年销售额近百亿。于刚和1号店是怎么过槛的？电商创业又有哪些秘诀？不管你是电商从业者，还是创业者，这篇六千字文都值得一读。<br/>　　<br/>提交<br/>　　五年多以前，1号店是什么？只是一个概念，一个梦想，一个愿景，而把这个概念变成现实是有巨大鸿沟的，因为概念如果停在在嘴上就永远只是一个概念。<br/>　　第一道槛：从职业经理人到创业者<br/>　　2008年，我和搭档刘峻岭都是戴尔的高管，一个管戴尔全球每年180亿美元的采购，一个管戴尔中国大区的销售，当时我们经常聚会，多数时间是谈工作。有一次，他把我拉在一起午餐，这次没谈工作，而是希望我和他一起出来创业。<br/>　　因为第一次在美国的创业给我带来非常美好的人生经历(注：于刚的第一次创业是在美国做航空管理软件，他将产品卖给了几乎所有的美国的大型航空公司)，所以当刘峻岭仅仅提出创业想法，还不是十分清楚怎么做的时候，我就答应他了。而这主要是基于一个信念：如果我们两人能够全身心投入的话，我们会创造更大的价值。<br/>　　提出来创业想法看似挺简单，其实很不易，因为当时我们已经是全球50强公司的资深高管，拿着丰厚的薪资和福利，创业就意味着要放弃戴尔给我们的所有东西。后来我们搬到上海浦东的张江高科技园区的一个十平米一张办公桌的办公室里，从零开始，这个决策是不好下的。但你没有失去的话就不会得到，所以我们破釜沉舟，做了这个决策。<br/>　　创业初期，心态非常重要，我们刚从职业经理人退下来创业的时候，坎坷很多，比如融资。我记得有一次我们去(上海)浦西去见一个30岁刚出头的VC合伙人。我和峻岭之前准备了非常充分的PPT，把核心竞争力、商务模式和市场分析写得清清楚楚。然而仅仅谈了10分钟，他就没兴趣了，开始给我和峻岭上课：说我们都是职业经理人，知道怎么把1做到10，但不相信我们能把0做到1。我和他争辩称，自己在美国创过业，从0做到过1。他说那是美国这是中国，然后足足给我们上了40多分钟的课。<br/>　　在回来的路上，我和峻岭一句话都没有说。可能在座的黑马营同学们在想，我当时是不是很有挫折感，以前做高管时被前呼后拥，现在突然遇到这种白眼。我可以告诉黑马营同学们，我没有任何挫折感，心里只在想一件事：将来我一定要证明他是错的。现在看来，这个投资人恐怕失去了他一生中最大的一次机会，可能永远也不会再有的机会！<br/>　　第二道槛：创业做什么<br/>　　于是，我和峻岭开始在张江一个只有一张桌子的小办公室里面创业，我们俩面对面一坐就是四个月。创业要做什么，这是我们要慎重考虑的一个问题，因为这次创业不能再像年轻时有足够的机会和时间，拍拍脑袋就创业了。我们一定要做一次成熟的创业，充分想透要做什么，怎么做，商务模式对不对，将来能不能赢利以及能不能创造价值。否则，连自己都不能说服的话，我们是承担不起机会和时间的损失。<br/>　　我们就在小房间里每天讨论十多个小时，所有的商务计划和假设都一个一个地过，所有的数据一个个地确认。假如不清楚，我们就出去做市场调查。后来，我们确信电商这个事业能够说服我们。因为我有在亚马逊做电子商务的经历，而且参与了亚马逊收购卓越的部分过程，知道中国电子商务的迅猛发展。创业选行业的话一定要选阳光型的行业，这点很重要，你不能逆水行舟，而要顺水行舟。而电子商务是一个好行业。<br/>　　怎么做?我们当时发现有很多垂直电商，比如图书、母婴、服装和相机数码。但是亚马逊的经历告诉我，电子商务一定是规模性的东西，不要分垂直品类的，因为一旦有了平台、流量以及顾客对你的信任，你就没有什么不可以卖。电子商务的特征就是不受时间和空间的限制，以某种垂直的品类起步也许比较容易，但如果把自己一直定位在那个品类比较深的话，你就会遇到很多瓶颈和困难。<br/>　　最早，我们提出网上超市的概念，主打食品、饮料、美容和护理等快速消费品。快消品有什么好处呢?它不像母婴产品只满足了妈妈和孩子的需求，而是满足了大众所需。获取顾客成本很高，留住顾客比获取顾客更重要，所以我们就选了这个黏性很强的品类。<br/>　　第三道槛：目录营销陷阱<br/>　　然而，网站还没有上线，我们就犯了一个很大错误——花了三个多月去做目录营销。当时，我们发现有公司通过目录营销比较成功，而当时我看到一个国际会议的材料也说电子商务的未来是线上和线下目录的结合。所以，我们花了3个多月的时间做了300页非常精致的目录，日以继夜的工作。因为以前在大公司待惯了，我们开始也很大手笔：第一次便印了10万份，每本成本十几块钱，这样100多万元就烧出去了。<br/>　　除了印刷成本，分发一本也需要几块钱。为了省钱，我们就派自己员工发，我也曾在小区发过目录，有天晚上，我还带着我一个在华盛顿大学做教授的朋友一起发目录，每人背一个学生包，但最后却被小区的保安给拦住了。<br/>　　目录发出去后，我们然后就非常焦急地等待，期望订单像雪片一样飞过来。然而，到晚上我们开始数定单的时候，才发现一共只有20个订单，并且绝大多是我们员工自己下的单。发了3万多本的时候，我们果断停掉了发送。<br/>　　之后，我就意识到我们做错了，因为目录这个东西是固态的，电子商务应该是动态的，比如库存信息和价格信息是无法改变的。而目录的修改周期是一个月，这一个月里所有东西都改不了，没库存的还在上面，价格变动也体现不出来。<br/>　　好在我们马上进行了修正，并开始寻找做电子商务的正确之路。<br/>　　第四道槛：建设企业文化<br/>　　然后，在招第一个员工之前，我们做了一件非常重要的事情——建立企业文化，因为一个企业没有文化是不可能基业常青的。所以，我们花了两个星期时间写了两页纸的企业文化精髓，显然这太长了，之后又缩减到半页纸，但觉得还太长，后来便浓缩到八个字：诚信、顾客、执行、创新。<br/>　　那又该怎样将这种文化根植在每个人身上?电子商务是一个虚拟的东西，跟顾客直接打交道最后只有配送员和客服。顾客怎么才能信任我们？这需要一点一滴去做，而不是你一天到晚只是讲。早期的时候，客服培训都是我和峻岭亲自培训，给她们讲：你们一定要站在顾客的那一面，甚至要站在公司的对立面为顾客着想。<br/>　　我们曾卖过一个叫石库门的老酒，这个酒当时在不同的销售渠道其酒盖上有不同的标识。有一个顾客买了就说，我们卖的是假货，因为酒盖符号和在别的地方买到的不一样。在解释一番后，顾客仍坚持要退货，客服就让顾客把货寄回来处理。我们就和客服讲，既然没有赢得顾客的信任就不应该再给顾客制造任何障碍。我们就派配送员去取回了货物，马上全款退回。<br/>　　我再举一个配送的例子。我们常常要求配送要超出顾客的期望值，这句话说很容易做很难。因为给配送员讲大道理是没有用的，他们只看别人是怎么做的。我们就每周例会时做故事分享，让他们讲自己做的超出顾客期望值的事情，比如我们一个配送员发现顾客的门没锁，他就给顾客打电话，一直在那儿看守了一个多小时等顾客回到家锁了门后才离开，这个故事很感人。以后，每个人就会把这个故事当成自己的准则，要思考再做什么事情才能超出顾客的期望值。<br/>　　也就是说，我们在不断形成新的标准，要做新的事情以超出顾客期望值，这样就逐渐建立起了一个真正有创业激情的团队。<br/>　　此外，我们所有会议室的命名都反映了我们企业文化的某一个因素或精髓，因为企业文化是一个潜移默化的东西，而不是说一次就够的。<br/>　　第五道槛：顾客体验<br/>　　要想赢，一定要聚焦在最重要的事情上面，1号店其实就聚焦在两个事情：顾客体验和供应链管理。<br/>　　先讲顾客体验。我们觉得顾客体验太容易被喊成口号了，我们不想喊口号，只想做。怎么做呢?我们聘请三方专业公司为我们做顾客体验调查，就把每一个员工的薪资奖金都和顾客体验指标挂钩起来，如果顾客体验上升了每个人都有奖金，下降了每个人都扣奖金。<br/>　　我们花费了三个多月才把这个政策推广了下去。因为每次往下推广就有部门推托，比如说，自己是做IT系统的，顾客体验及采购和自己没有关系，那是配送员和客服的事情。其实，他理解错了，顾客体验是一个综合考量，比如顾客有没有买到他想要的商品，买的价格好不好，这是采购的事情;但使用的系统是不是足够顺畅，这是IT系统的事情。所以，每个人都要承担起责任，即使HR等支持部门，你也有责任敦促那些顾客体验做得不好的部门去改善。<br/>　　最后一次会议，峻岭和我对20多个高管直接表明：你可以自己选择，但是你要留在1号店就必须接受这个理念。我们是2011年推广下去的，起初顾客满意度是84.4%，到了当年年底就达到了92.2%，非常见效。<br/>　　此外，我们每个星期都有一个回顾一周业务的会议，前半个小时我们叫做VOC(voice of customer)，就是聆听顾客的声音，把我们所有的顾客体验指标和顾客体验调查都和盘托出。甚至，直接播放把顾客给我们投诉的录音以让大家都知道有什么问题。还有，1号店所有高管，都要定期做仓库、配送、客服的实践。，两星期前我从仓库体验回来以后就写了一个有30个问题的清单。要求每个高管实践完都要提出问题和改进方案。顾客体验问题，就需要这样一点一滴的去解决，365天每天都去改善。<br/>　　第六道槛：供应链管理<br/>　　电子商务难就难在供应链管理这块，因为它的精髓就是把顾客想要的商品在他想要的地方和时间送到其手中，所以供应链管理就成为了电子商务最核心的点。但我们有信心做好，因为我以前在大学教书是教供应链管理的，后来在亚马逊和戴尔，自己负责的也是供应链和采购。而且，我第一次创业做过各种各样的系统。所以我们希望供应链系统能打造成为我们的核心竞争力。<br/>　　我们是怎么打造的?当时1号店上线的时候，我们就做了一个最重要的决策——自己开发所有的系统。而目前，除了OA系统、财务等是买的，其余所有的系统都是我们自己开发的。之所以这样做，是因为电子商务将来一定要规模化运营，这就意味着系统变得非常重要，<br/>　　当时，我们也对系统定下几个标准，而这也成了我们做的最正确决策之一。<br/>　　第一个，系统必须集成化。我们不允许有各种各样独立的零散系统，所以可以看到现在一个系统里面有供应商、采购、仓储、配送、客服、价格、类目管理和营销管理等各种大小模块。这样就保证所有系统用的数据都是一样的，供应链和配送等各种信息也都是透明的。<br/>　　第二，系统一定要实时。我们一定要实时地看到所有资源的使用情况，这个要求比较高一点。<br/>　　第三，这个系统一定要是柔性的。它要允许我们不断地去尝试新的商务模式，允许做错的时候可以改。<br/>　　第四，这个系统一定要是可扩的。现在看起来，这个标准越来越发重要，因为当我们流量、销售、商品越来越多越来越大的时候，我们不需要改基础架构，只需增加模块和服务器就行了。<br/>　　目前，1号店在武汉有1000多人的IT团队，负责开发各种各样的系统，比如仓库管理系统，从库位优化、拣货优化、分拣优化到最后出库分拣优化等等。许多第三方物流也在使用我们的系统，因为我们的系统可以帮助他规划路径以及反馈所有信息。这一决策确实给我们打下了很好的基础。<br/>　　电商创业感悟：柔性决策<br/>　　回顾这五年，我们走了很多弯路，但是我们有一点做得非常好：很快地做决策，发现不正确就马上纠正过来，再走到正确的路上。<br/>　　在电子商务领域，决策的速度往往比决策质量还重要，因为电商发展时间窗口很短，不快速做决策的话，时机就没有了，你就没有机会往下面做了。举例讲，当初我们的虚拟超市“无限1号店”假若不上线，一个星期后，我们的竞争对手便会上线类似的产品，而正是因为我们上线，他们就取消掉了他们的策划。后来有人告诉我，我们的概念刚刚出来，对手也已经筹备好了。<br/>　　作为一种创新的业态，你很难讲电商的哪个模式是对或者错。所以我们现在一是不要怕犯错，二是犯错没关系，因为我们可以从中学到很多东西。而最为关键的便是要有一个纠错机制，下次不要犯同样的错误，或者下次更聪明一些。<br/>　　在这上面，我有很多体会，刚开始我们找了一个5000平方米的仓库，看着空空荡荡的，当时心里就疑问将来能填满吗。结果2009年就爆仓了，到现在我们至少爆仓了6次，每次计划都是不够的。比如说我们现在不愿意去建仓库，因为需要大量投资，而且这个仓库很可能地理位置不够好，招工也不好招，面积又不足够大，但这些都是很现实的问题。所以，我宁愿让我们的决策变得非常柔性化，可以随时改变。<br/>　　课堂互动<br/>　　黑马营学员：<br/>　　我有一个关于企业哲学的问题，在顾客、股东和员工之间的排序上，我想知道您是怎么排的?<br/>　　于刚：<br/>　　排序是非常简单的事情，顾客一定是第一位的，因为没有顾客你这个企业做不成，这意味着对员工和股东都没有了价值。第二是员工，因为没有人才也做不出事情。如果有了顾客和人才，把企业做强了，每个股东才会受益。<br/>　　黑马营学员：<br/>　　1号店第一年线上销售额大概是400多万元，第二年是4600多万，到了第三年却增长到了8亿。我想问您，什么因素导致了1号店在短短一年之内有这种爆炸式地增长?它的核心关键点是什么?<br/>　　于刚：<br/>　　每一个创业的路都不是直线上升的，很长时间都在摸索，但是一旦找对了商业模式，就会快速地发展。<br/>　　我觉得我们当时有很多方法，一个就是我们开始找对了互联网推广的方法，第一年我们开始做目录，目录不行的时候，好几万本目录全压箱底，目录不行，太贵了。然后我们开始做海报，发现海报效果不错，但是销售像打鸡血一样，一发出去销售起来了，过几天又没有了。<br/>　　后来，我们开始跟互联网公司合作，这点我觉得是非常好的经验，我们非常开放地去合作，甚至跟我们竞争对手合作。最早我们跟天涯合作，天涯有这么多会员，1号店却没有，这样就把客流引到我们这里来。此外，我们还与易迅等购物平台展开互换流量等方面的合作，我把我的顾客引到他那儿，他把顾客引到我这儿，最后顾客有自己的选择。我们是秉持着非常开放的心态慢慢找到了营销方法。<br/>　　同时，我们迅速扩张了品类。电子商务中影响顾客体验最重要的标准有几个：品种、价格、及时送货率、售后服务及系统等。品种是排在第一位的重要因素，因为假若你没有顾客想要的东西，后面服务怎么好都没有用，所以我们那一年品种大幅度的上升，这也让我们快速成长。<br/>　　课堂笔记<br/>　　卢小旭(黑马营六期学员、小旭音乐创始人)：于总的1号店从事食品销售，属于“高危”行业，加上于总的海归背景对国内电商行业不熟悉，初期起步可谓步履蹒跚。但1号店几年来的迅猛发展说明几个问题：于总最熟悉和有经验的供应链管理对于百货电商具有极其重要的作用;创业需要激情，于总提到每天睁开眼睛开始就充满了一种兴奋劲儿，尽管每日的工作中充满了困难，但正是这种迎难而上的干劲儿才使得1号店近年迅速崛起，值得每一个创业者学习!<br/>　　张捷(黑马营六期学员、上海伯第信息创始人)：于总最后补充的创业最重要的三句话让我记忆犹新：<br/>　　创业是马拉松，不是百米冲刺，从一开始就要从长远着想。第二，创业一定要迎难而上，不难也就没什么价值了。第三，创业最重要的是激情，如果你把它当一件事，而不是事业的话，你肯定就做不成。<br/>　　另外，快速决策和及时纠偏是我学到的重要方法论。<br/>　　李银环(黑马营六期学员、河南恒瑞源董事长)：上海课程结束，于刚博士给我们留下了很深的印象，于博士儒雅、淡定，像百战归来的英雄。
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6759/</link>
<title><![CDATA[为何程序员完成最后20%的工作需要的时间跟之前的80%一样多？]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Thu, 24 Oct 2013 06:01:40 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6759/</guid> 
<description>
<![CDATA[ 
	http://www.36kr.com/p/207155.html
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6660/</link>
<title><![CDATA[Axure RP 6 原型设计精髓]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Mon, 16 Sep 2013 14:40:30 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6660/</guid> 
<description>
<![CDATA[ 
	下载PDf：<br/>http://ishare.iask.sina.com.cn/f/37411096.html<br/><br/>Axure RP 6原型设计精髓》是一本结合UX系统阐述Axure原型设计的书。<br/>先介绍Axure的界面、术语、功能，然后以一个中型示例项目为背景依次探讨UX项目的创建流程和Axure的使用技巧。出于简洁性考虑，《Axure RP 6原型设计精髓》对原型设计过程进行了简化，但依旧由易到难完整地阐述了一个UX项目的要素，如定义商业和技术需求、建立用例和流程图、构建高（低）保真线框图、设计交互、编注说明、产出详细UX规格文档及追踪迭代。<br/>摘录自：<br/>http://baike.baidu.com/link?url=D9lcTE2DmCN9GLPPUKa--XqzvN_EGqqRWaMH4GeI3xNpQFM8-k9NZteaezEN1qMdDue1IfhRbkbXUtN2QGI9lq<br/>
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6640/</link>
<title><![CDATA[什么叫颠覆式创新，颠覆性创新的几个最重要的特征。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Fri, 06 Sep 2013 03:44:16 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6640/</guid> 
<description>
<![CDATA[ 
	核心：颠覆性创新的几个最重要的特征：<br/>1）你把一个很贵的东西做的很便宜。<br/>2）你把一个要钱的东西做成了不要钱的。<br/>3）你把一个很难获得的东西变得很容易获得。<br/>4）你把原来一个很难用的一个东西变得非常的简单。<br/>你能带Ipad，绝不带笔记本。<br/>我买了一个单反相机，而每天出门还是拿个手机拍照，是吧？这在人性中，人是最懒惰的，人是最图省事儿的，最后，你所发现成功的，都跟人性中的七宗罪......<br/>就是把别人收费的版本，迅速降低成本（到互联网时代直接免费了，免费是是互联网的精髓。）<br/><br/>视频：http://www.geekpark.net/cast/view/172119
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6599/</link>
<title><![CDATA[Raspberry Pi sous vide water bath,Improved temperature control for Raspberry Pi sous vide。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Mon, 19 Aug 2013 12:42:35 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6599/</guid> 
<description>
<![CDATA[ 
	I’ve been very happy with the results from my Raspberry Pi controlled water bath for sous vide cooking, but I knew that the control loop could be improved. Past runs show fairly continued oscillation:<br/>Roast beef temps2<br/>Roast beef run at 60C<br/>I’ve been keeping track of the average power for my control loop, which has been coming out at 22%. So i modified the code to have a bias of 22%, and here’s the result:<br/>Test run at 55C<br/>Test run at 55C<br/>Overall much more stable. The occasional hiccups are probably caused by the remote socket failing to receive off commands. There’s a 3C overshoot at the start, which I hope to have fixed by entering the control loop from initial warm up 3C earlier. <br/><textarea name="code" class="c" rows="15" cols="100">
import os
from subprocess import Popen, PIPE, call
from optparse import OptionParser
from time import sleep
def tempdata():
&nbsp;&nbsp;&nbsp;&nbsp;# Replace 28-000003ae0350 with the address of your DS18B20
&nbsp;&nbsp;&nbsp;&nbsp;pipe = Popen([&quot;cat&quot;,&quot;/sys/bus/w1/devices/w1_bus_master1/28-000003ea0350/w1_slave&quot;], stdout=PIPE)
&nbsp;&nbsp;&nbsp;&nbsp;result = pipe.communicate()[0]
&nbsp;&nbsp;&nbsp;&nbsp;result_list = result.split(&quot;=&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;temp_mC = int(result_list[-1]) # temp in milliCelcius
&nbsp;&nbsp;&nbsp;&nbsp;return temp_mC
def setup_1wire():
&nbsp;&nbsp;os.system(&quot;sudo modprobe w1-gpio &amp;&amp; sudo modprobe w1-therm&quot;)
def turn_on():
&nbsp;&nbsp;os.system(&quot;sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 on&quot;)
def turn_off():
&nbsp;&nbsp;os.system(&quot;sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 off&quot;)
#Get command line options
parser = OptionParser()
parser.add_option(&quot;-t&quot;, &quot;--target&quot;, type = int, default = 55)
parser.add_option(&quot;-p&quot;, &quot;--prop&quot;, type = int, default = 6)
parser.add_option(&quot;-i&quot;, &quot;--integral&quot;, type = int, default = 2)
parser.add_option(&quot;-b&quot;, &quot;--bias&quot;, type = int, default = 22)
(options, args) = parser.parse_args()
target = options.target * 1000
print (&#039;Target temp is %d&#039; % (options.target))
P = options.prop
I = options.integral
B = options.bias
# Initialise some variables for the control loop
interror = 0
pwr_cnt=1
pwr_tot=0
# Setup 1Wire for DS18B20
setup_1wire()
# Turn on for initial ramp up
state=&quot;on&quot;
turn_on()
temperature=tempdata()
print(&quot;Initial temperature ramp up&quot;)
while (target - temperature &gt; 6000):
&nbsp;&nbsp;&nbsp;&nbsp;sleep(15)
&nbsp;&nbsp;&nbsp;&nbsp;temperature=tempdata()
&nbsp;&nbsp;&nbsp;&nbsp;print(temperature)
print(&quot;Entering control loop&quot;)
while True:
&nbsp;&nbsp;&nbsp;&nbsp;temperature=tempdata()
&nbsp;&nbsp;&nbsp;&nbsp;print(temperature)
&nbsp;&nbsp;&nbsp;&nbsp;error = target - temperature
&nbsp;&nbsp;&nbsp;&nbsp;interror = interror + error
&nbsp;&nbsp;&nbsp;&nbsp;power = B + ((P * error) + ((I * interror)/100))/100
&nbsp;&nbsp;&nbsp;&nbsp;print power
&nbsp;&nbsp;&nbsp;&nbsp;# Make sure that if we should be off then we are
&nbsp;&nbsp;&nbsp;&nbsp;if (state==&quot;off&quot;):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn_off()
&nbsp;&nbsp;&nbsp;&nbsp;# Long duration pulse width modulation
&nbsp;&nbsp;&nbsp;&nbsp;for x in range (1, 100):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (power &gt; x):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (state==&quot;off&quot;):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state=&quot;on&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&quot;On&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn_on()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (state==&quot;on&quot;):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state=&quot;off&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&quot;Off&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn_off()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1)
</textarea><br/>http://blog.thestateofme.com/2013/05/12/improved-temperature-control-for-raspberry-pi-sous-vide/<br/>Temperature control for a sous vide water bath is a popular application for hobbyist microcontroller kits, with lots of well documented projects out there. My favourite is the Sous Vader – if only for the attention to detail in the decal on the box.<br/>I’ve been planning my own for a little while, and got some DS18B20 temperature probes a little while ago. The long Easter weekend break finally brought me some time to progress the project.<br/>Danger – High Voltage<br/>I have an old slow cooker that’s perfectly good for doing pot roast. It’s been falling to bits for some time, and I’ve patched it up with a Sugru sample I got at Monkigras. I had thoughts of hacking it directly (and perhaps even building in a Raspberry Pi), but common sense took hold and I decided on a route that didn’t involve directly manipulating mains electricity.<br/>To turn the slow cooker on and off I got hold of a radio controlled mains socket from Maplin – they’re available without the controller (which I didn’t need) for £7.99.<br/>I found a library to control the remote socket on github – Raspberry Strogonanoff (thanks Duncan McGregor, and a clever choice of project name). This uses a Sparkfun 434MHz RF Link Transmitter (which as suggested by Duncan I got from Protopic).<br/>Getting Raspberry Strogonanoff working was the easier part of the whole set up. Having looked at the socket to establish that it was set to channel 4 button 1 I simply ran this line to turn it on:<br/>sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 on<br/>and this to turn it off again:<br/>sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 off<br/>Getting control<br/>A water bath is a good example of a control system. The water and pot collectively have quite a high specific heat capacity, and there’s quite a bit of latency between turning off power and the rise in temperature stopping. The standard way of dealing with this is to use a PID Controller (see this explanation for a BBQ application for something more straightforward than the Wikipedia article). The Sous Vader seems to have worked with just a PI controller (effectively D=0), so I tried that first. There is a python implementation of a PID controller, which I didn’t spend the time to integrate.<br/>Tuning the control loop<br/>This is the tricky and time consuming part. In theory there should be a nice library out there that figures out correct settings for P, I and D based on observed data, but in practice it seems that most people resort to manual tuning.<br/>The hardware<br/>I started out with things on a breadboard using my usual home made Pi Cobbler, but as I want to use this in the kitchen I’ve created a more permanent setup using a Ciseco Slice of Pi, which at £3.90&nbsp;&nbsp;is a very inexpensive small project board. I used one of the header strips in the Slice of Pi kit as a place to plug in the 434MHz transceiver and the temperature probes (so it would be easy to use parts in other projects). It was then simply a case of soldering some connecting wires to the appropriate power (5v for the transceiver and 3.3v for the DS18B20), GPIO (0 for the transceiver and 7 for the DS18B20) and GND:<br/>The system pictured above has an Edimax WiFi dongle so that I can control and monitor the whole thing when it’s in the kitchen..<br/>The software<br/>Update 14 Apr 2013 – the code (slightly improved over what’s below) is now available on GitHub along with (hopefully comprehensive) installation instructions.<br/>It’s not especially pretty, but seems to be doing the job:<br/><textarea name="code" class="c" rows="15" cols="100">
import os
from subprocess import Popen, PIPE, call
from optparse import OptionParser
from time import sleep
def tempdata():
&nbsp;&nbsp;&nbsp;&nbsp;# Replace 28-000003ae0350 with the address of your DS18B20
&nbsp;&nbsp;&nbsp;&nbsp;pipe = Popen([&quot;cat&quot;,&quot;/sys/bus/w1/devices/w1_bus_master1/28-000003ea0350/w1_slave&quot;], stdout=PIPE)
&nbsp;&nbsp;&nbsp;&nbsp;result = pipe.communicate()[0]
&nbsp;&nbsp;&nbsp;&nbsp;result_list = result.split(&quot;=&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;temp_mC = int(result_list[-1]) # temp in milliCelcius
&nbsp;&nbsp;&nbsp;&nbsp;return temp_mC
def setup_1wire():
&nbsp;&nbsp;os.system(&quot;sudo modprobe w1-gpio &amp;&amp; sudo modprobe w1-therm&quot;)
def turn_on():
&nbsp;&nbsp;os.system(&quot;sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 on&quot;)
def turn_off():
&nbsp;&nbsp;os.system(&quot;sudo ./strogonanoff_sender.py --channel 4 --button 1 --gpio 0 off&quot;)
#Get command line options
parser = OptionParser()
parser.add_option(&quot;-t&quot;, &quot;--target&quot;, type = int, default = 55)
parser.add_option(&quot;-p&quot;, &quot;--prop&quot;, type = int, default = 8)
parser.add_option(&quot;-i&quot;, &quot;--integral&quot;, type = int, default = 2)
(options, args) = parser.parse_args()
target = options.target * 1000
print (&#039;Target temp is %d&#039; % (options.target))
P = options.prop
I = options.integral
# Initialise some variables for the control loop
interror = 0
pwr_cnt=1
pwr_tot=0
# Setup 1Wire for DS18B20
setup_1wire()
# Turn on for initial ramp up
state=&quot;on&quot;
turn_on()
temperature=tempdata()
print(&quot;Initial temperature ramp up&quot;)
while (target - temperature &gt; 3000):
&nbsp;&nbsp;&nbsp;&nbsp;sleep(15)
&nbsp;&nbsp;&nbsp;&nbsp;temperature=tempdata()
&nbsp;&nbsp;&nbsp;&nbsp;print(temperature)
print(&quot;Entering control loop&quot;)
while True:
&nbsp;&nbsp;&nbsp;&nbsp;temperature=tempdata()
&nbsp;&nbsp;&nbsp;&nbsp;print(temperature)
&nbsp;&nbsp;&nbsp;&nbsp;error = target - temperature
&nbsp;&nbsp;&nbsp;&nbsp;interror = interror + error
&nbsp;&nbsp;&nbsp;&nbsp;power = ((P * error) + ((I * interror)/100))/100
&nbsp;&nbsp;&nbsp;&nbsp;print power
&nbsp;&nbsp;&nbsp;&nbsp;if (power &gt; 0):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pwr_tot = pwr_tot + power
&nbsp;&nbsp;&nbsp;&nbsp;pwr_ave = pwr_tot / pwr_cnt
&nbsp;&nbsp;&nbsp;&nbsp;pwr_cnt = pwr_cnt + 1
&nbsp;&nbsp;&nbsp;&nbsp;print pwr_ave
&nbsp;&nbsp;&nbsp;&nbsp;# Long duration pulse width modulation
&nbsp;&nbsp;&nbsp;&nbsp;for x in range (1, 100):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (power &gt; x):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (state==&quot;off&quot;):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state=&quot;on&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&quot;On&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn_on()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (state==&quot;on&quot;):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state=&quot;off&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&quot;Off&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;turn_off()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1)
</textarea><br/>Conclusion<br/>I’ve not had the chance to use the water bath for cooking yet, but I’m very much looking forward to trying out a few steaks and maybe some Sunday roasts. I’ll report back on the results.<br/>来自：http://blog.thestateofme.com/2013/03/31/raspberry-pi-sous-vide-water-bath/<br/>参考：<br/>http://blog.thestateofme.com/2013/01/28/ds18b20-rpi/<br/>http://www.flashingleds.net/sousvader/sousvader.html<br/>自己参考：<br/>（1）Raspberry Pi PWM编写的方法：<br/>http://jackxiang.com/post/6591/<br/>（2）树莓派Raspberry和ds18B20接合,可以接多个Ds18B20：http://jackxiang.com/post/6588/
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6588/</link>
<title><![CDATA[树莓派Raspberry和ds18B20接合,可以接多个Ds18B20。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Fri, 16 Aug 2013 01:41:21 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6588/</guid> 
<description>
<![CDATA[ 
	Raspberry Pi 使用DS18B20:<br/>一、硬件准备<br/>1、树莓派（Raspberry Pi）一个<br/>2、DS18B20温度传感器一个（淘宝大概5元左右）<br/>3、4.7kΩ电阻一个 或 DS18B20模块一个（笔者用，淘宝1.5元一个，其实就是店家帮忙把电阻焊好了，接线稍好看些）。<br/>4、杜邦线三根（双头母）<br/>二、接线方式（如图所示）<br/>Raspberry &lt;wbr&gt;Pi &lt;wbr&gt;使用DS18B20温度传感器<br/>三、确认硬件接线是否正确并生效，并读取温度<br/>1、首先升级内核(可忽略，但如果版本较老，可能影响设备读取)<br/>apt-get update<br/>apt-get upgrade<br/>2、确认设备是否生效<br/>sudo modprobe w1-gpio<br/>sudo modprobe w1-therm<br/>cd /sys/bus/w1/devices/<br/>ls<br/>显示结果：<br/>pi@raspberrypi:~$ cd /sys/bus/w1/devices/<br/>pi@raspberrypi:/sys/bus/w1/devices$ ls<br/>28-00000494cb79 w1_bus_master1<br/>28-00000494cb79就是笔者外接的温度传感器设备，但并不是每个客户端都显示一样的，这个是传感器的序列号。<br/>3、查看当前温度<br/>cd 28-00000494cb79<br/>cat w1_slave<br/>显示结果：<br/>70 01 4b 46 7f ff 10 10 e1 : crc=e1 YES<br/>70 01 4b 46 7f ff 10 10 e1 t=23000<br/>第二行的t=23000就是当前的温度值，要换算成摄氏度，除以1000，即当前温度为23000/1000=23摄氏度。<br/>四、用python读取温度值<br/>文件存放:/home/pi/temperature.py<br/>内容如下：<br/>#/home/pi/temperature.py<br/>#打开温度传感器文件<br/>tfile = open(&quot;/sys/bus/w1/devices/28-00000494cb79/w1_slave&quot;)<br/>#读取文件所有内容<br/>text = tfile.read()<br/>#关闭文件<br/>tfile.close()<br/>#用换行符分割字符串成数组，并取第二行<br/>secondline = text.split(&quot;&#92;n&quot;)[1]<br/>#用空格分割字符串成数组，并取最后一个，即t=23000<br/>temperaturedata = secondline.split(&quot; &quot;)[9]<br/>#取t=后面的数值，并转换为浮点型<br/>temperature = float(temperaturedata[2:])<br/>#转换单位为摄氏度<br/>temperature = temperature / 1000<br/>#打印值<br/>print temperature<br/>在命令行运行，即可得出结果数值:<br/>python /home/pi/temperature.py<br/>五、上报到yeelink<br/>yeelink是国内比较知名的免费物联网数据平台，国外有COSM（https://cosm.com）。<br/>申请yeelink账号及添加设备和传感器，以及API的学习，本文跳过，请大家自行去学习一下。<br/>根据yeelink API的规则，我们需要提供一个文本文件，内容为一段JSON，如下：<br/>&#123;<br/>“timestamp”:”2012-03-15T16:13:14″,<br/>“value”:294.34<br/>&#125;<br/>若未指定timestamp, 服务器会自动加上当前时间，所以本文的操作不添加该字段<br/>1、修改python，将温度值用JSON格式保存到一个文本文件，全部如下：<br/>#/home/pi/temperature.py<br/>tfile = open(&quot;/sys/bus/w1/devices/28-00000494cb79/w1_slave&quot;)<br/>text = tfile.read()<br/>tfile.close()<br/>secondline = text.split(&quot;&#92;n&quot;)[1]<br/>temperaturedata = secondline.split(&quot; &quot;)[9]<br/>temperature = float(temperaturedata[2:])<br/>temperature = temperature / 1000<br/>res = &#039;&#123;&quot;value&quot;:%f&#125;&#039; %temperature<br/>output = open(&#039;/home/pi/datafile.txt&#039;, &#039;w&#039;)<br/>output.write(res)<br/>output.close<br/>python将温度值写入：/home/pi/datafile.txt<br/>2、新增yeelink.sh脚本<br/>文件位置：/home/pi/yeelink.sh<br/>内容如下：<br/>sudo python /home/pi/temperature.py<br/>curl --request POST --data-binary @&quot;/home/pi/datafile.txt&quot; --header&quot;U-ApiKey:XXXXXXXXXXXXXXXX&quot;http://api.yeelink.net/v1.0/device/1969/sensor/2533/datapoints<br/>将U-ApiKey:XXXXXXXXXXXXXXXX替换为自已账户的API Key。<br/>后面的URL也需要替换为自己申请的传感器URL。<br/>3、添加到计划任务<br/>#为脚本增加可执行权限<br/>sudo chmod +x yeelink.sh<br/>#将脚本加入cronjob（计划任务）<br/>sudo crontab -e<br/>#在cornjob文件中添加下面一行，并保存(表示10分钟执行一下脚本，时间可自行修改)<br/>*/10 * * * * /home/pi/yeelink.sh<br/>完了！<br/>我的温度传感器数据展示页面：http://www.yeelink.net/devices/1969<br/>参考文档：<br/>http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/temperature/<br/>http://blog.turningdigital.com/2012/09/raspberry-pi-ds18b20-temperature-sensor-rrdtool/<br/>http://webshed.org/wiki/RaspberryPI_DS1820<br/>http://baike.baidu.com/view/1341776.htm <br/><br/>以上来自：http://blog.sina.com.cn/s/blog_3cb6a78c0101a46w.html<br/>————————————————————————————————————————————————<br/><br/><br/><br/>有画图程序值得参考：<br/>blog.turningdigital.com/2012/09/raspberry-pi-ds18b20-temperature-sensor-rrdtool/<br/><br/><br/><br/>一：首先升级内核(可忽略，但如果版本较老，可能影响设备读取)<br/>apt-get update<br/>apt-get upgrade<br/>二：<br/>温度传感器用的是DS18B20，由于树莓派是工作在linux下，所以无法直接使用C来做驱动，因此我使用的是国外大牛做好的驱动，直接编译进内核<br/>具体方式，进入命令行（通过ssh或者直接连显示器）<br/>输入如下命令<br/>sudo wget http://www.frank-buss.de/raspberrypi/kernel-rpi-w1.tgz<br/>sudo tar -xzf kernel-rpi-w1.tgz<br/>sudo rm -f kernel-rpi-w1.tgz<br/>sudo cd /lib/modules<br/>sudo wget http://www.frank-buss.de/raspberrypi/modules-rpi-w1.tgz<br/>sudo tar -xzf modules-rpi-w1.tgz<br/>sudo rm -f modules-rpi-w1.tgz<br/>sudo sync<br/>sudo reboot<br/><br/>然后等待机器重启重新加载1-wire设备的驱动，也就是给18b20的驱动。<br/><br/>重启完成之后，按图所示连接18B20和树莓派：来自：http://www.guokr.com/post/438477/<br/>http://img1.guokr.com/thumbnail/SCe-ZqjIdJeTog3r28g8Ji5COD9U1lS3vnoHAB13aIvdAwAAYAIAAEpQ_590x362.jpg<br/><br/>http://www.guokr.com/post/438477/<br/>The response will either have YES or NO at the end of the first line. If it is yes, then the temperature will be at the end of the second line, in 1/000 degrees C. So, in the example above, the temperature is actually read as 20.687 and then 26.125 degrees C.<br/>If you have more than one Sensor connected, you&#039;ll see multiple 28-xxx files. Each one will have the unique serial number so you may want to plug one in at a time, look at what file is created, and label the sensor!<br/>摘录来自：http://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing/ds18b20<br/>参考：http://www.2fz1.com/?tag=ds18b20<br/><br/>PWM输出：http://www.eeboard.com/bbs/thread-7174-1-1.html<br/><br/>以上就可以实现一个温度控制了。<br/><br/><br/>背景：前面我用过at89s52和ds18B20做过温度传感器，也用tsic506做过，发现单片机里的线太多了（因为有按钮什么的接线，控制电路接通和断开的线等），这个raspberry pi可以通过触摸屏来实现这个按钮，也就减少了线，而且不用com口接至上位机，也就是说可以直接显示出来温度曲线，再就是这个linux有一个watchdog，不用单片机那样用上那个硬件看门狗都可以保证系统不会死，死了linux会拉起来的，稳定性增强了（这块要注意5V的电源一定要好，否则系统一样不稳定，我用欧版I9000的原装电源发现很不错。），外加上一个wifi的usb无线网卡，可以实现发到任何互联网的地方（用php或python等）。<br/><br/><br/><br/>温度传感器用的是DS18B20，由于树莓派是工作在linux下，所以无法直接使用C来做驱动，因此我使用的是国外大牛做好的驱动，直接编译进内核<br/>具体方式，进入命令行（通过ssh或者直接连显示器）<br/>输入如下命令<br/>sudo wget http://www.frank-buss.de/raspberrypi/kernel-rpi-w1.tgz<br/>sudo tar -xzf kernel-rpi-w1.tgz<br/>sudo rm -f kernel-rpi-w1.tgz<br/>sudo cd /lib/modules<br/>sudo wget http://www.frank-buss.de/raspberrypi/modules-rpi-w1.tgz<br/>sudo tar -xzf modules-rpi-w1.tgz<br/>sudo rm -f modules-rpi-w1.tgz<br/>sudo sync<br/>sudo reboot<br/><br/>然后等待机器重启重新加载1-wire设备的驱动，也就是给18b20的驱动。<br/><br/>重启完成之后，按图所示连接18B20和树莓派<br/><br/>接下来，在命令行输入<br/>sudo modprobe w1-gpio<br/>sudo modprobe w1-therm<br/>(以上两条命令需要在/etc/rc.loca这个启动脚本里添加,添加的时候去掉sudo,这样可以不用每次启动都要手动加载w1模块了)<br/>ls /sys/bus/w1/devices/w1&#92; bus&#92; master<br/>会显示<br/>其中28开头的就是28b20设备了<br/><br/>读取温度则用如下命令<br/>cat /sys/bus/w1/devices/w1&#92; bus&#92; master /28-*/w1_slave<br/>t的值就是温度，除以1000就是摄氏度<br/><br/><br/>再接下来就是程序部分了,树莓派是运行在linux下的,同时又带有python的解释器.于是我打算写一个python脚本来登录新浪微博,然后发表状态.网上搜了一圈,对于python实在是无力,看到别人用新浪微博python SDK做的脚本,就是不知道怎么移植过来.万般无奈之下,用了一个别人写的模拟登陆新浪微博的脚本,只修改了里面的账户和密码,当然改成我自己的了,发现居然可以登录.运行脚本,显示 Login success!(晚上公司的路由的动态DNS又挂了,家里没法连上树莓的FTP,脚本文件暂时明天上传)<br/><br/><br/>来自：http://www.guokr.com/post/438477/<br/>Raspberry Pi PWM编写的方法:<br/>http://jackxiang.com/post/6591/
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post/6487/</link>
<title><![CDATA[单片机4x4键盘设计]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[产品管理]]></category>
<pubDate>Wed, 26 Jun 2013 14:54:29 +0000</pubDate> 
<guid>http://www.jackxiang.com/post/6487/</guid> 
<description>
<![CDATA[ 
	矩阵键盘是单片机编程中所使用的键盘.<br/>1.矩阵式键盘的结构与工作原理<br/>　　在键盘中按键数量较多时，为了减少I/O口的占用，通常将按键排列成矩阵形式，如图1所示。在矩阵式键盘中，每条水平线和垂直线在交叉处不直接连通，而是通过一个按键加以连接。这样，一个端口（如P1口）就可以构成4*4=16个按键，比之直接将端口线用于键盘多出了一倍，而且线数越多，区别越明显，比如再多加一条线就可以构成20键的键盘，而直接用端口线则只能多出一键（9键）。由此可见，在需要的键数比较多时，采用矩阵法来做键盘是合理的。<br/>　　矩阵式结构的键盘显然比直接法要复杂一些，识别也要复杂一些，上图中，列线通过电阻接正电源，并将行线所接的单片机的I/O口作为输出端，而列线所接的I/O口则作为输入。这样，当按键没有按下时，所有的输出端都是高电平，代表无键按下。行线输出是低电平，一旦有键按下，则输入线就会被拉低，这样，通过读入输入线的状态就可得知是否有键按下了。具体的识别及编程方法如下所述。<br/><br/>　　2、矩阵式键盘的按键识别方法 <br/>　　确定矩阵式键盘上何键被按下介绍一种“行扫描法”。<br/>　　行扫描法 行扫描法又称为逐行（或列）扫描查询法，是一种最常用的按键识别方法，如上图所示键盘，介绍过程如下。<br/>　　1、判断键盘中有无键按下 将全部行线Y0-Y3置低电平，然后检测列线的状态。只要有一列的电平为低，则表示键盘中有键被按下，而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平，则键盘中无键按下。 <br/>　　2、判断闭合键所在的位置 在确认有键按下后，即可进入确定具体闭合键的过程。其方法是：依次将行线置为低电平，即在置某根行线为低电平时，其它线为高电平。在确定某根行线位置为低电平后，再逐行检测各列线的电平状态。若某列为低，则该列线与置为低电平的行线交叉处的按键就是闭合的按键。 <br/>　　下面给出一个具体的例子：<br/>　　图仍如上所示。8031单片机的P1口用作键盘I/O口，键盘的列线接到P1口的低4位，键盘的行线接到P1口的高4位。列线P1.0-P1.3分别接有4个上拉电阻到正电源+5V，并把列线P1.0-P1.3设置为输入线，行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。<br/>　　1、检测当前是否有键被按下。检测的方法是P1.4-P1.7输出全“0”，读取P1.0-P1.3的状态，若P1.0-P1.3为全“1”，则无键闭合，否则有键闭合。 <br/>　　2、去除键抖动。当检测到有键按下后，延时一段时间再做下一步的检测判断。 <br/>　　3、若有键被按下，应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出： <br/>　　　P1.7 1 1 1 0<br/>　　　P1.6 1 1 0 1<br/>　　　P1.5 1 0 1 1<br/>　　　P1.4 0 1 1 1<br/>　　在每组行输出时读取P1.0-P1.3，若全为“1”，则表示为“0”这一行没有键闭合，否则有键闭合。由此得到闭合键的行值和列值，然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值<br/>　　4、为了保证键每闭合一次CPU仅作一次处理，必须却除键释放时的抖动。 <br/><br/>　　键盘扫描程序：<br/>　　从以上分析得到键盘扫描程序的流程图如图2所示。程序如下<br/>SCAN: MOV P1,#0FH<br/>MOV A,P1<br/>ANL A,#0FH<br/>CJNE A,#0FH,NEXT1<br/>SJMP NEXT3<br/>NEXT1: ACALL D20MS<br/>MOV A,#0EFH<br/>NEXT2: MOV R1,A<br/>MOV P1,A<br/>MOV A,P1<br/>ANL A,#0FH<br/>CJNE A,#0FH,KCODE;<br/>MOV A,R1<br/>SETB C<br/>RLC A<br/>JC NEXT2<br/>NEXT3: MOV R0,#00H <br/>RET<br/>KCODE: MOV B,#0FBH<br/>NEXT4: RRC A<br/>INC B<br/>JC NEXT4<br/>MOV A,R1<br/>SWAP A<br/>NEXT5: RRC A<br/>INC B<br/>INC B<br/>INC B<br/>INC B<br/>JC NEXT5<br/>NEXT6: MOV A,P1<br/>ANL A,#0FH<br/>CJNE A,#0FH,NEXT6<br/>MOV R0,#0FFH<br/>RET <br/>　　键盘处理程序就作这么一个简单的介绍，实际上，键盘、显示处理是很复杂的，它往往占到一个应用程序的大部份代码，可见其重要性，但说到，这种复杂并不来自于单片机的本身，而是来自于操作者的习惯等等问题，因此，在编写键盘处理程序之前，最好先把它从逻辑上理清，然后用适当的算法表示出来，最后再去写代码，这样，才能快速有效地写好代码。<br/>　　键盘是由一组规则排列的按键组成，一个按键实际上是一个开关元件，也就是说键盘是一组规则排列的开关。<br/><br/>    键盘工作原理<br/><br/>    1．按键的分类<br/>按键按照结构原理可分为两类，一类是触点式开关按键，如机械式开关、导电橡胶式开关等；另一类是无触点开关按键，如电气式按键，磁感应按键等。前者造价低，后者寿命长。目前，微机系统中最常见的是触点式开关按键。<br/>按键按照接口原理可分为编码键盘与非编码键盘两类，这两类键盘的主要区别是识别键符及给出相应键码的方法。编码键盘主要是用硬件来实现对键的识别，非编码键盘主要是由软件来实现键盘的定义与识别。<br/>全编码键盘能够由硬件逻辑自动提供与键对应的编码，此外，一般还具有去抖动和多键、窜键保护电路，这种键盘使用方便，但需要较多的硬件，价格较贵，一般的单片机应用系统较少采用。非编码键盘只简单地提供行和列的矩阵，其它工作均由软件完成。由于其经济实用，较多地应用于单片机系统中。下面将重点介绍非编码键盘接口。 <br/>2．键输入原理<br/>在单片机应用系统中，除了复位按键有专门的复位电路及专一的复位功能外，其它按键都是以开关状态来设置控制功能或输入数据。当所设置的功能键或数字键按下时，计算机应用系统应完成该按键所设定的功能，键信息输入是与软件结构密切相关的过程。<br/>    对于一组键或一个键盘，总有一个接口电路与CPU相连。CPU可以采用查询或中断方式了解有无将键输入并检查是哪一个键按下，将该键号送入累加器ACC，然后通过跳转指令转入执行该键的功能程序，执行完后再返回主程序。<br/>3．按键结构与特点<br/>微机键盘通常使用机械触点式按键开关，其主要功能是把机械上的通断转换成为电气上的逻辑关系。也就是说，它能提供标准的TTL逻辑电平，以便与通用数字系统的逻辑电平相容。<br/>机械式按键再按下或释放时，由于机械弹性作用的影响，通常伴随有一定时间的触点机械抖动，然后其触点才稳定下来。其抖动过程如图7.2所示，抖动时间的长短与开关的机械特性有关，一般为5~10ms。<br/><br/>左图  按键触点的机械抖动<br/>在触点抖动期间检测按键的通与断状态，可能导致判断出错。即按键一次按下或释放被错误地认为是多次操作，这种情况是不允许出现的。为了克服按键触点机械抖动所致的检测误判，必须采取去抖动措施，可从硬件、软件两方面予以考虑。在键数较少时，可采用硬件去抖，而当键数较多时，采用软件去抖。<br/>在硬件上可采用在键输出端加R-S触发器(双稳态触发器)或单稳态触发器构成去抖动电路，图7.3是一种由R-S触发器构成的去抖动电路，当触发器一旦翻转，触点抖动不会对其产生任何影响。<br/>电路工作过程如下：按键未按下时，a = 0，b = 1，输出Q = 1，按键按下时，因按键的机械弹性作用的影响，使按键产生抖动，当开关没有稳定到达b端时，因与非门2输出为0反馈到与非门1的输入端，封锁了与非门1，双稳态电路的状态不会改变，输出保持为1，输出Q不会产生抖动的波形。当开关稳定到达b端时，因a = 1，b = 0，使Q = 0，双稳态电路状态发生翻转。当释放按键时，在开关未稳定到达a端时，因Q = 0，封锁了与非门2，双稳态电路的状态不变，输出Q保持不变，消除了后沿的抖动波形。当开关稳定到达b端时，因a = 0，b = 0，使Q = 1，双稳态电路状态发生翻转，输出Q重新返回原状态。由此             右图 双稳态去抖电路<br/>可见，键盘输出经双稳态电路之后，输出已变为规范的矩形方波。<br/>软件上采取的措施是：在检测到有按键按下时，执行一个10ms左右（具体时间应视所使用的按键进行调整）的延时程序后，再确认该键电平是否仍保持闭合状态电平，若仍保持闭合状态电平，则确认该键处于闭合状态；同理，在检测到该键释放后，也应采用相同的步骤进行确认，从而可消除抖动的影响。<br/>    4．按键编码<br/>一组按键或键盘都要通过I/O口线查询按键的开关状态。根据键盘结构的不同，采用不同的编码。无论有无编码，以及采用什么编码，最后都要转换成为与累加器中数值相对应的键值，以实现按键功能程序的跳转。<br/>5．编制键盘程序<br/>一个完善的键盘控制程序应具备以下功能：<br/>（1）检测有无按键按下，并采取硬件或软件措施，消除键盘按键机械触点抖动的影响。<br/>（2）有可靠的逻辑处理办法。每次只处理一个按键，其间对任何按键的操作对系统不产生影响，且无论一次按键时间有多长，系统仅执行一次按键功能程序。<br/>（3）准确输出按键值（或键号），以满足跳转指令要求。<br/><br/>    独立式按键<br/>   <br/>单片机控制系统中，往往只需要几个功能键，此时，可采用独立式按键结构。<br/>1．独立式按键结构<br/>独立式按键是直接用I/O口线构成的单个按键电路，其特点是每个按键单独占用一根I/O          <br/>               左图   独立式按键电路<br/><br/><br/>口线，每个按键的工作不会影响其它I/O口线的状态。独立式按键的典型应用如图7.4所示。<br/>独立式按键电路配置灵活，软件结构简单，但每个按键必须占用一根I/O口线，因此，在按键较多时，I/O口线浪费较大，不宜采用。<br/>图7.4中按键输入均采用低电平有效，此外，上拉电阻保证了按键断开时，I/O口线有确定的高电平。当I/O口线内部有上拉电阻时，外电路可不接上拉电阻。<br/>2．独立式按键的软件结构<br/>独立式按键软件常采用查询式结构。先逐位查询每根I/O口线的输入状态，如某一根I/O口线输入为低电平，则可确认该I/O口线所对应的按键已按下，然后，再转向该键的功能处理程序。图7.4中的I/O口采用P1口，请读者自行编制相应的软件。<br/>7．1．3  矩阵式按键<br/>单片机系统中，若使按键较多时，通常采用矩阵式（也称行列式）键盘。<br/>1．矩阵式键盘的结构及原理<br/>矩阵式键盘由行线和列线组成，按键位于行、列线的交叉点上，其结构如下图所示。                                          <br/><br/>由图可知，一个4×4的行、列结构可以构成一个含有16个按键的键盘，显然，在按键数量较多时，矩阵式键盘较之独立式按键键盘要节省很多I/O口。<br/>矩阵式键盘中，行、列线分别连接到按键开关的两端，行线通过上拉电阻接到＋5V上。当无键按下时，行线处于高电平状态；当有键按下时，行、列线将导通，此时，行线电平将由与此行线相连的列线电平决定。这是识别按键是否按下的关键。然而，矩阵键盘中的行线、列线和多个键相连，各按键按下与否均影响该键所在行线和列线的电平，各按键间将相互影响，因此，必须将行线、列线信号配合起来作适当处理，才能确定闭合键的位置。<br/>2．矩阵式键盘按键的识别<br/>识别按键的方法很多，其中，最常见的方法是扫描法。下面以图7.5中8号键的识别为例来说明扫描法识别按键的过程。<br/>    按键按下时，与此键相连的行线与列线导通，行线在无键按下时处在高电平，显然，如果让所有的列线也处在高电平，那么，按键按下与否不会引起行线电平的变化，因此，必须使所有列线处在低电平，只有这样，当有键按下时，该键所在的行电平才会由高电平变为低电平。CPU根据行电平的变化，便能判定相应的行有键按下。8号键按下时，第2行一定为低电平，然而，第2行为低电平时，能否肯定是8号键按下呢？回答是否定的，因为9、10、11号键按下同样使第2行为低电平。为进一步确定具体键，不能使所有列线在同一时刻都处在低电平，可在某一时刻只让一条列线处于低电平，其余列线均处于高电平，另一时刻，让下一列处在低电平，依此循环，这种依次轮流每次选通一列的工作方式称为键盘扫描。采用键盘扫描后，再来观察8号键按下时的工作过程，当第0列处于低电平时，第2行处于低电平，而第1、2、3列处于低电平时，第2行却处在高电平，由此可判定按下的键应是第2行与第0列的交叉点，即8号键。<br/>    3．键盘的编码<br/>对于独立式按键键盘，因按键数量少，可根据实际需要灵活编码。对于矩阵式键盘，按键的位置由行号和列号唯一确定，因此可分别对行号和列号进行二进制编码，然后将两值合成一个字节，高4位是行号，低4位是列号。如图7.5中的8号键，它位于第2行，第0列，因此，其键盘编码应为20H。采用上述编码对于不同行的键离散性较大，不利于散转指令对按键进行处理。因此，可采用依次排列键号的方式对安排进行编码。以图7.5中的4×4键盘为例，可将键号编码为：01H、02H、03H…0EH、0FH、10H等16个键号。编码相互转换可通过计算或查表的方法实现。<br/>4．键盘的工作方式<br/>在单片机应用系统中，键盘扫描只是CPU的工作内容之一。CPU对键盘的响应取决于键盘的工作方式，键盘的工作方式应根据实际应用系统中CPU的工作状况而定，其选取的原则是既要保证CPU能及时响应按键操作，又不要过多占用CPU的工作时间。通常，键盘的工作方式有三种，即编程扫描、定时扫描和中断扫描。<br/>    1）编程扫描方式<br/>编程扫描方式是利用CPU完成其它工作的空余调用键盘扫描子程序来响应键盘输入的要求。在执行键功能程序时，CPU不再响应键输入要求，直到CPU重新扫描键盘为止。<br/>键盘扫描程序一般应包括以下内容：<br/>（1）判别有无键按下。<br/>（2）键盘扫描取得闭合键的行、列值。<br/>（3）用计算法或查表法得到键值。<br/>（4）判断闭合键是否释放，如没释放则继续等待。<br/>（5）将闭合键键号保存，同时转去执行该闭合键的功能。
]]>
</description>
</item>
</channel>
</rss>