本帖最后由 水乐天 于 2012-9-12 17:50 编辑
最近听弘毅讲LaunchPad搞活动促销,超便宜,于是俺买了10块...慢慢弄总会用到滴{:soso_e154:},这几天反复折磨有一点小小心得,不敢独享,于是打算写出来与大伙分享。
下面放出是淘宝网店地址,注意如果数量比较多的话需要有团购代码的,需要的童鞋可以去购买:
http://item.taobao.com/item.htm?id=16603403744
----------------------------------------------------------------------------------------------------------------------------
首先声明下:本文不针对零基础的朋友,如果对一般开发常识、C语言、C++完全没有了解,请绕行。
准备工作一:
俗话说工欲善其事必先利其器,首先我们来谈谈编译环境的选择:
官方的编译环境如果没有使用过请参考《Energia介绍--MSP430的Arduino IDE》或直接下载
但是官方的编译器有各种问题。。。比如中文注释不能书写。。。于是我仅用官方的编译器做调试用途,平时书写代码....还是算了吧。
我建议Windows用户选择UtralEdit IOS及Linux用户选择Sublime text 2
另外为了让我们的代码看起来更舒服 附赠代码格式化工具
----------------------------------------------------------------------------------------------------------------------------
准备工作二:
之后我们要对手头的LaunchPad做些小小的处理:
第一步 将RXD与TXD 两个跳线横过来,因为串口输出到PC需要这两个端口,否则无法进行串口输出。
第二步 将P1.6和P1.0两个LED等的跳线拔掉,因为这两个端口跟I2C端口冲突,所以在调试的时候如果你不需要这两个LED最好将其拔掉。
第三步 注意如果你的程序要使用串口的话,那么3号和4号引脚尽量不要使用,否则会影响串口数据的输出。
为了让大家更清楚地了解,如下图所示:
----------------------------------------------------------------------------------------------------------------------------
1.1 首先让我们来看一个51的程序。
本人本行是开发上位系统软件基本是硬件盲,在写这个之前完全没接触过51单片机,也没写过51的程序,各位硬件高手不要见笑哈。但是我觉得从太简单的程序入手没意思哈,于是从公司同事手中借来个台湾燃太的TN901红外温度传感器和51的范例程序。于是我们就拿这个程序开始我们的改造好了。如下图所示:
因为51的完整代码比较长还包括LCD的显示,所以我们摘主要的来看,想看完整代码点下载
主要我们需要转换的部分的包括这几个部分
一、端口定义: - sbit TN_Data = P1^0; //定义TN9接口
- sbit TN_Clk = P1^2;
- sbit TN_ACK = P1^4;
复制代码
二、主程序部分: - /*----------------------------------主程序入口-----------------------------------*/
- void main()
- {
- LCD_Init(); //LCD初始化
- Delay5Ms();
- LCD_Write_String(0, 0, Range);
- LCD_Write_String(0, 1, table);
- Delay400Ms();
- TN_ACK = 1;
- while(1)
- {
- TN_ACK = 0;
- TN_ReadData(0x4c); //目标温度的第一个字节为0x4c
- if((ReadData[0] == 0x4c) && (ReadData[4] == 0x0d)) //每帧的最后一个字节为0x0d
- {
- TN_GetData_Target();
- }
- DelayMs(1);
- TN_ACK = 0;
- TN_ReadData(0x66); //环境温度的第一个字节为0x66
- if((ReadData[0] == 0x66) && (ReadData[4] == 0x0d)) //每帧的最后一个字节为0x0d
- {
- TN_GetData_Temp();
- }
- }
- }
复制代码
三、IIC接口数据传输: - void TN_ReadData(uchar flag) //读数据
- {
- uchar i,j,k;
- bit BitState = 0; //每次发七帧
- for(k=0;k<7;k++)
- {
- for(j=0;j<5;j++) //每帧5个字节
- {
- for(i=0;i<8;i++)
- {
- while(TN_Clk);
- BitState= TN_Data;
- ReadData[j]= ReadData[j]<<1;
- ReadData[j]= ReadData[j]|BitState;
- while(!TN_Clk);
- }
- }
- if(ReadData[0]==flag) k=8;
- }
- TN_ACK=1;
- }
复制代码
虽然我从没写过51的程序,但是我觉得大体上51程序结构都应该差不多,所以我按照这种方法来转换就好,这个程序搞定了基本其它程序也类似如此。
首先我们来转换,第一部分端口的定义,51这里用的类型是sbit,对应应该是byte 0或1 估计是标识每个端口的高低电平,但是我们这里与51程序的含义不同应该标识具体的端口号,所以我们这里采用int类型,如下所示:
- int TN_Data=7;
- int TN_Clk=8;
- int TN_ACK=9;
复制代码
之后我们来看程序的入口函数,注意这里的端口值改变比如 TN_ACK=1; (51代码原来很精简哦)其实是给ACK端口赋值为高电平,所以我们这里应该对应的写法是- pinMode(TN_ACK, OUTPUT);//指定ACK引脚为输出脚
- digitalWrite(TN_ACK,HIGH);//将指定端口输出为高电平
复制代码
为了处理方便我们将51主方法中的代码分割在Setup和Loop方法中执行于是,我们将其分割为两个部分,将初始化部分放在Setup中执行,While(1)中的部分放在Loop中执行,如下所示: - //初始化部分
- void setup()
- {
- pinMode(TN_Clk, INPUT); //设定时钟口为输入端口
- pinMode(TN_ACK, OUTPUT); //设定ACK口为输出端口
- digitalWrite(TN_ACK,HIGH);//在ACK口输出高电平
- }
- //采集部分
- void loop()
- {
- digitalWrite(TN_ACK,LOW);
- TN_ReadData(0x4c); //目标温度的第一个字节为0x4c
- if((ReadData[0]==0x4c)&&(ReadData[4]==0x0d))//每帧的最后一个字节为0x0d
- {
- Target=TN_GetData_Target();
- }
-
- delay(1);
-
- digitalWrite(TN_ACK,LOW);
- TN_ReadData(0x66); //环境温度的第一个字节为0x66
-
- if((ReadData[0]==0x66)&&(ReadData[4]==0x0d))//每帧的最后一个字节为0x0d
- {
- Temp=TN_GetData_Temp();
- }
- }
复制代码
然后我们来看IIC数据传输的部分,大体逻辑我是这样理解的,时钟作为一个标志位,每当时钟高低电平改变的时候采用将1字节的数据存储起来并左移一位,直到出现结束标志位为止,这里我们要注意下51程序中while(TN_Clk);这样的地方。在这里我们TN_Clk代表的不是具体端口的高低电平所以要换成这样的写法- while(val)
- {
- val = digitalRead(TN_Clk);//获取端口的高低电平
- }
复制代码
之后我们把这部分的代码转换过来,如下所示: - void TN_ReadData(char flag) //读数据
- {
- char i, j, k;
- byte BitState = 0; //每次发七帧
- for(k = 0; k < 7; k++)
- {
- for(j = 0; j < 5; j++) //每帧5个字节
- {
- for(i = 0; i < 8; i++)
- {
- int val = digitalRead(TN_Clk);//注意这里51是直接读端口号所以我们要进行转换
- while(val)
- {
- val = digitalRead(TN_Clk);
- }
- BitState = digitalRead(TN_Data);
- ReadData[j] = ReadData[j] << 1;
- ReadData[j] = ReadData[j] | BitState;
- while(!val)
- {
- val = digitalRead(TN_Clk);
- }
- }
- }
- if(ReadData[0] == flag) k = 8;
- }
- digitalWrite(TN_ACK, HIGH);
- }
复制代码
再给这个程序加上串口输出的部分,我们这次的内容就大功告成了:) - int TN_Data = 15;
- int TN_Clk = 14;
- int TN_ACK = 13;
- unsigned char ReadData[5];
- short Temp,Target;
- void setup()
- {
- Serial.begin(9600);
- pinMode(TN_Clk, INPUT);//
- pinMode(TN_ACK, OUTPUT);
- digitalWrite(TN_ACK,HIGH);
- }
- void loop()
- {
- digitalWrite(TN_ACK,LOW);
- TN_ReadData(0x4c); //目标温度的第一个字节为0x4c
- if((ReadData[0]==0x4c)&&(ReadData[4]==0x0d)) //每帧的最后一个字节为0x0d
- {
- Target=TN_GetData_Target();
- }
-
- delay(1);
-
- digitalWrite(TN_ACK,LOW);
- TN_ReadData(0x66); //环境温度的第一个字节为0x66
-
- if((ReadData[0]==0x66)&&(ReadData[4]==0x0d)) //每帧的最后一个字节为0x0d
- {
- Temp=TN_GetData_Temp();
- }
- }
- void SerialValue()
- {
- Serial.print("Target: ");
- Serial.print(Target, DEC);
- Serial.println(" C");
- Serial.print("Temp: ");
- Serial.print(Temp, DEC);
- Serial.println(" C");
- }
- void TN_ReadData(char flag) //读数据
- {
- char i,j,k;
- byte BitState = 0; //每次发七帧
- for(k=0;k<7;k++)
- {
- for(j=0;j<5;j++) //每帧5个字节
- {
- for(i=0;i<8;i++)
- {
- int val= digitalRead(TN_Clk);
- while(val)
- {
- val = digitalRead(TN_Clk);
- }
- //val = digitalRead(TN_Clk);
- BitState= digitalRead(TN_Data);
- ReadData[j]= ReadData[j]<<1;
- ReadData[j]= ReadData[j]|BitState;
- while(!val)
- {
- val = digitalRead(TN_Clk);
- }
- }
- }
- if(ReadData[0]==flag) k=8;
- }
- digitalWrite(TN_ACK,HIGH);
- }
- int TN_GetData_Temp()
- {
- int Temp;
- Temp=(ReadData[1]<<8)|ReadData[2];
- Temp = (float)Temp/16 - 273.15;
- Temp=Temp*100; //温度值乘100,以方便计算小数点后两位
-
- return Temp;
- }
- int TN_GetData_Target()
- {
- int Target;
- Target=(ReadData[1]<<8)|ReadData[2];
- Target = (float)Target/16 - 273.15;
- Target=Target*100; //温度值乘100,以方便计算小数点后两位
-
- return Target;
- }
复制代码
最后我们来总结下51到Arduino程序转换需要注意的地方:
第一:端口定义的转换,因为端口取值的方式不同所以写法上要转换下,个人觉得从设计模式的角度上讲,51的端口取值方式虽然很方便,但是容易造成变量定义时的混淆,有时候多写几行代码未必是坏事。
第二:因为Arduino的基本结构包含Setup和Loop,51这里一般用一个死循环直接实现。所以这里要注意下程序哦分割。
第三:注意效率问题,比如Serial输出这样的方法消耗一定的时间,一次可能影响很小,但是如果套在多层循环中和需要速度的处理中影响会很大。有兴趣的朋友可以试试把串口输出的实际时间消耗。最后把程序模块化分割,冗余的逻辑。
其他方面我觉得程序移植起来还是很方便的,基本大部分51的代码都可以用Arduino来实现。本次因为这是测试代码所以有些小乱,我将会在后面的文章中详细讲解下如何整理和封装代码的步骤,让大家写起程序更加模块化:)
|