51单片机AD转换、串口蓝牙通讯、labview上位机显示
功能:单片机模拟数字转化,将数字信号通过蓝牙或者串口传输给电脑,电脑上labview显示出一个图表。
我这里实际使用是探测光信号强弱的:
光信号——>光电探测器——>单片机电压转化为数字信号(AD转化)——>单片机通过串口发送出——>labview接收显示
单片机采用非常简单,别人常说它垃圾,可能确实有点垃圾,但是我却很喜欢的stc12c5a60s2,自带AD转化,有2个串口美滋滋,引脚图如下:
我使用P1.1口作为模拟信号输入,P1.3作为串口把数据实时传输出去。
voltagetemp_int=(int)(voltagetemp*1000);
voltagetemp_a = voltagetemp_int /100;
voltagetemp_b = voltagetemp_int %100;
UartSendChar('l');
UartSendChar('m');
UartSendChar(voltagetemp_a);
UartSendChar(voltagetemp_b);
UartSendChar('n');
UartSendChar('o');
根据上面代码,可以知道,传出去的数据,自己为了弄一个校验识别,先发送字符l和m,再发送真实数据,再发送字符n和o表示这一次数据发送结束。模拟信号电压真实值在0-5v之间,这里为了精度高一点显示,先乘以1000,再把高2位和低2位分别取出来,分别发送出去。
还是以前本科时候写的主要代码C语言,拿过来改改用,或许不是很规范。问题很大。懒得改了。
完事之后文件夹如下。
主函数代码:ceshi.c
#include <12c5a60s2.h>
#include "intrins.h"
#include <stc12delay.h>
#include <ADchange.h>
#include <math.h>
#include <uart.h>
int light=0;
uint scan_num=0;
float voltagetemp=0;
int voltagetemp_int=0;
int voltagetemp_a=0;
int voltagetemp_b=0;
int t_int=0;
void main()
{
UartInit();
AD_init();
while(1)
{
scan_num++;
if(scan_num>30)
{
scan_num=0;
AD_get(1);
light=initvoltage1;delay(1);
voltagetemp=light/1024.0*5;
voltagetemp_int=(int)(voltagetemp*1000);
voltagetemp_a = voltagetemp_int /100;
voltagetemp_b = voltagetemp_int %100;
// UartSendChar(voltagetemp_int);
UartSendChar('l');
UartSendChar('m');
UartSendChar(voltagetemp_a);
UartSendChar(voltagetemp_b);
UartSendChar('n');
UartSendChar('o');
}
}
}
————
ADchange.h内容如下:
idata uint initvoltage1;
void AD_init()
{
P1ASF=0x03; //P1 0 1 口作为模拟功能AD使用
ADC_RES=0; //清零转换结果寄存器高8位
ADC_RESL=0; //清零转换结果寄存器低2位
ADC_CONTR=0x80;//开启AD电源
delay(1); //等待1ms,让AD电源稳定
}
void AD_get(char channel) //我这里只能取0 和 1 通道
{
ADC_CONTR=0x88|channel; //开启AD转换1000 1000 自定通道 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0
_nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时,其值才能够保证被设置进ADC_CONTR 寄存器
while(!(ADC_CONTR&0x10)); //等待转换完成
ADC_CONTR&=0xe7; //关闭AD转换,ADC_FLAG位由软件清0
initvoltage1=ADC_RES*4+ADC_RESL;
//voltagetemp=initvoltage1/1024.0*5;
//FtoS(voltagetemp);
//return str; //返回AD转换完成的10位数据(16进制)
}
————
stc12delay.h内容如下:
#ifndef __STC12DELAY_H__
#define __STC12DELAY_H__
#define uchar unsigned char
#define uint unsigned int
/*****相关宏定义***/
/* exact-width signed integer types */
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long int int64_t;
/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
11.0592 1T
void delay01ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
//延时n ms
void delaynms(unsigned int n)
{ unsigned int i;
for(i=0;i<n;i++)
delay01ms();
}
//也是延时 n ms
void delay(unsigned int n)
{ unsigned int i;
for(i=0;i<n;i++)
delay01ms();
}
11.0592 1T
void delay1ms12(void) //误差 -0.018084490741us
{
unsigned char a,b,c;
for(c=8;c>0;c--)
for(b=197;b>0;b--)
for(a=2;a>0;a--);
}
void delaynms12 (unsigned int n)
{ unsigned int i;
for(i=0;i<n;i++)
delay1ms12();
}
#endif
————
uart.h内容如下:
void UartInit();
void UartSendChar(unsigned char ch); //向外发送字节
void UartSendStr(unsigned char *pStr); //向外发送字符串
void UartInit()
{
//串口2,用于舵机控制器
//串口1,用于接收上位机发出指令
S2CON = 0x50; // SCON: serail mode 1, 8-bit UART 定时器1作为波特率的发生器
SCON = 0x50;
AUXR=0X15;
BRT=(int)(256-((11059200/9600)/32));
EA = 1;
ES = 1;
}
//串口2有关
void UartSendChar(unsigned char ch) //向外发送字节
{
S2BUF = ch;
while(!(S2CON&S2TI));
S2CON&=~S2TI;
}
void UartSendStr(uchar *pStr) //向外发送字符串
{
while(*pStr != 0)
{
S2BUF = *pStr++;
while(!(S2CON&S2TI));
S2CON&=~S2TI;
}
}
把生成的hex文件下载到单片机之后,单片机就不停的向串口发送:l,m,数据1,数据2,n,o,l,m,数据1,数据2,n,o, l,m,数据1,数据2,n,o, ……
好,然后是labview做的上位机界面的接收,显示。
先看界面情况:
然后看前面板程序:
先配置串口(和单片机内配置保持一致就行了),电脑上就可以选择串口号,包括蓝牙也可以直接选择电脑蓝牙对应的串口号:
再经过一个while循环,循环内进行主要数据的接受和处理。先visa读取数据,这里每次读取10个数据,一边直接显示在缓存区,同时下面接一根线将其转化为图标。
下面将visa读取的数据实际上是一个字符类型的,转化为字节数组。
下面接for循环,来解析分别把这个10个元素的一维数组内的数据索引出来。
索引数组就是脚本语言中的a[5],把a数组中第6个元素取出来。
下面就分别把这个数组中,a[i],a[i+1],a[i+2],a[i+3]这4个元素分别拿出来。i是遍历的从0-9。
然后判断,如果满足a[i] =109,a[i+3]=110,(109和110分别是asc码的字符m和n) ,那么 就把a[i+1]和a[i+2]这2个真实数据拿出来进行一个类型转换,再转化为真实的电压数据显示出来即可。
完整的labview代码如下:
Over~