蓝牙数据传输设计
报告
软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载
作者 王雷
日期 2011-5-25
摘要: 目前, 无线数据传输在日常和工业控制领域中应用得越来越广泛,方便人们的同时,也极大提高了工作效率。本项目通过无线蓝牙模块使PC机与单片机之间进行通信,并在单片机加显示器件,将PC机发送的汉字显示出来。由于单片机的硬件资源很有限, 寻址和计算能力都远低于 PC 机, 显示汉字受到限制。因此将这个工作交给 PC 机, 让 PC 机访问汉字库并提取汉字字模, 再通过蓝牙模块将汉字字模发送给单片机。通过该方法实现数据的无线传输及汉字汉字显示。
一、系统框图
该蓝牙汉字无线传输系统主要由两大部分构成,一是PC端,实现汉字字模的提取,并发送。二是MUC端,采用STC89C52单片机作为下位机主机,接收PC端发来的汉字字模数据,并将其显示在屏幕上。两者间是通过蓝牙模块联系起来的,这里采用的是广州汇承信息科技有限公司自主研发的蓝牙传输模块hc-05,该模块提供了现成的UART接口,能够方便的与PC和MUC现实无缝连接。如图1
图1 整体框图
二、硬件设计
下面是将以上整体框图具体到各个硬件电路:
图2 PC端的硬件接线图
图2是PC端的硬件接线图,由两部分组成,一是,蓝牙发送模块,接收从串口发来的数据,然后按照蓝牙传输
协议
离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载
对数据进行打包,再通过天线发射出去。另一部分,是一个USB接口转为串口的部件,这里考虑到,现在有很多PC机没有提供串口,所以通过这个部件从USB端口虚拟出一个串口,与蓝牙模块相接。需要注意的是,蓝牙模块是采用3.3v供电,并且采用3.3v的TTL电平,因此要求USB转串口的模块提供3.3v电源及逻辑电平。另外如果是直接采用的电脑串口,则需要做电平转换。
图3 蓝牙模块接线图
HC-5为短距离无线传输提供了完美的解决方案,它提供了很多主流的通信接口,图3实现的是串口通信,在完整的系统中,需要一个发射模块做为主机,一个接收模块做为从机。工作前,需要对这两个模块进行配置,可以通过串口调试软件发送AT指令,使用模块完成相应配置以达到应用要求,也可以在工作中进行动态配置。在本项目中采用的是一主一从模块,按默认配置即可。在工作时,如果两模块的指示灯同频闪,说明已经配对成功,此时可以进行数据传输了。否则应检查硬件接线及软件配置。
图4 MCU端的硬件接线图
下位机主机STC89C52是MCS-51系列的单片机,以它为核心构成系统的MCU端部分。图4显示了它的外围接线图。该MCU部分与其它51核单片机一样,由复位电路,振荡电路,外加5v直流电源组成了MCU的最小系统。保证单片机能够正常运行。外围显示器件使用TFT2.4英寸的液晶显示器,它的数据端DB0~DB7与P1口相连,控制端分别接在P2口的前4个脚。单片机的串口与接收蓝牙模块的串口相连,与发送端不一样的只是采用了一个ASM1117将5v的电压转换成3.3v供蓝牙模块使用。
三、软件设计
PC端的编程
利用VC提供的MFC,建立一个基于对话框的MFC应用程序。在对话框上放置各种控件,画出所需应用程序的图形界面。如下图
图2 应用程序界面
为了接收用户输入的汉字,需放置一个文本编辑框,将编辑框关联一个字符串变量m_send,以便下级处理。在图2界面中还放置一个编辑框用以显示数据的发送状态m_re,当用户单击Send按钮时,程序将执行“发送” 按钮的消息处理函数。如下
void CComDlg::OnSend()
{
if(num==0)
{
sendmessage(0);
m_re="正在发送...";
UpdateData(false);
}
else
{
m_re="未发送完成,请稍后尝试!";
UpdateData(false);
}
}
首先判断全局变量num是否等于0,为0表示就绪状态,此时可以发送数据。非0则表示还未发送完成,并在状态编辑框中显示提示信息。当发送完成之后num将被置0,恢复到就绪状态。num的置0是在串口响应函数中实现的。串口事件消息处理函数如下
void CComDlg::OnOnCommMscomm1()
{
// TODO: Add your control notification handler code here
int resEvent;
resEvent = m_mscom.GetCommEvent();
if(resEvent == 2)
{
VARIANT temp;
temp = m_mscom.GetInput();
unsigned short *t = temp.bstrVal;
if(*t==1)
{
for(long y=0;y<=2000;y++);//延时,为了与下位机速度的匹配
sendmessage(++num);//发送第num个字符
if(num==m_send.GetLength()/2)//判断是否发送完成
{num=0; m_re="发送完成!";}
}
UpdateData(false);
}
}
当从串口接收到1个字符时(通过串口初始化时设置),将触发MSComm事件中的事件2。因此会进入if复合语句中执行。先将接收到的字符取出来,然后判断MUC端是否成功的接收到了数据,这里是预先在MCU中指定了当它成功接收时,返回1。否则就不返回值。所以这里的判断语句是看接收到的字符是否等于1。如果接收成功,则继续发送下一个汉字,至到发送完为止。这时就将num清0,使它处于就绪状态。同时也在状态编辑框反应出来。
采用这种方式可以大大提高数据传输的准确性。另外,在以上两个函数中匀调用一个sendmessage()函数,以下是该字模提取函数的定义
void CComDlg::sendmessage(int x)
{
UpdateData();
const char* pBuf=(LPCTSTR)m_send;
BYTE ch[32]={0};
unsigned char QM[50]={0},WM[50]={0};
len=m_send.GetLength();
long Addr[50]={0};
CString str,str1="";
if(x
内容
财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容
是按照字节存放的, 即把 16× 16 个 “位” 变成 32 个 “字节”来存放。另外, 每个汉字在字库中有唯一的区位码与之对应, 根据字的机内码可以确定其区位码及其在字库中的起始位置, 就可以从字库中取出汉字字模。具体步骤如下:
根据汉字的机内码推算出区位码:
区码=机内码高字节- A0H
位码=机内码底字节- A0H
根据区位码计算出汉字在字库中的偏移量(即汉字在字库中的位置) :
偏移量 L=[(区码- 1)× 94+(位码- 1)]× 32
从该偏移地址读取 32 个字节, 就是相关汉字的点阵字模代码。
该函数代码的编写正是基于这个思想的。该函数还实现了将一个汉字发送到串口的功能。代码注释在已标明。在发送按钮的消息处理函数和串口事件消息处理函数中正是通过调用这个函数来实现数据发送的。至此,通过以上三个核心的函数就能够将数据正确的发送出去了。
下面是MCU端的软件实现。
MCU端的编程
单片机与PC间采用串口通讯,故必须使两端的波特率一致。PC端通过串口控件的m_mscom.SetSettings方法设置串口参数。而在MCU端是通过定时器T1来设置的,这里将波特率设置为9600,其串口相关的初始化代码如下
/*串口初始化*/
void uart_init()
{
SCON = 0x50;//选择串口方式1
TMOD = 0x20;//选择8位自动重装定时方式 方式2
TH1 = 0xfd; //2400bps f4
TL1 = 0xfd;//设置波特率为9600bps
fd
TR1 = 1;
//定时器使能
}
同时也要对中断进行初始化,代码如下
/*中断初始化*/
void int_init()
{
EA = 1;
//总中断
ES =1;
//串口中断
}
主函数采用查询的方式等待串口的触发,其代码如下
void main()
{
int_init();
uart_init();
lcd_init();
while(1) ;
}
在主函数中调用了两个函数对串口及串口中断初始化,之后,就可以对串口送来数据在串口中断子程序进行处理。以下是该子程序的代码。
/*串口中断子程序*/
void interrupt_uart() interrupt 4
{
if(TI)
{
TI = 0 ;
REN = 1;
}
if(RI)
{
RI = 0;
num[conter]=SBUF;
conter++;
if(conter==32)
{
REN=0;
conter = 0;
if(i%12==0)
j=0;
PutGB1616(40+j*16,40+i/12*16,0x0000,0xffff);
i++;
j++;
delayms(500);//延时,等侍字符有充分的时间在LCD上打印出来
SBUF =1;
}
}
}
当串口中断中的计数器等于32时,表明一个汉字的字模已经完整的被接收到。此时数据送到LCD上显示,并且返回字符1给PC端,表示这个字模已经被成功的接收到了。让PC机继续发送下一个汉字字模。函数中的PutGB1616是将buffer也就是num数组中的点阵数据显示出来的函数。第一二个参数是设置显示位置,第三四个参数分别是前景色与背景色。下面是MCU端的全部代码
#include
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#define WINDOW_XADDR_START
0x0050 // Horizontal Start Address Set
#define WINDOW_XADDR_END
0x0051 // Horizontal End Address Set
#define WINDOW_YADDR_START
0x0052 // Vertical Start Address Set
#define WINDOW_YADDR_END
0x0053 // Vertical End Address Set
#define GRAM_XADDR
0x0020 // GRAM Horizontal Address Set
#define GRAM_YADDR
0x0021 // GRAM Vertical Address Set
#define GRAMWR
0x0022 // memory write
sbit RS=P2^0;
//寄存器选择
sbit RW=P2^1;
//写入
sbit RES=P2^3;
//复位
sbit CS=P2^4; //片选
uint16 i = 0 ,j=0;
uint8 conter = 0;
static uint8 num[32] = {0};
/*****************************函数声明******************************/
void uart_init();
void int_init();
void Write_Cmd(unsigned char DH,unsigned char DL);
void Write_Data(unsigned char DH,unsigned char DL);
void delayms(unsigned int count);
void Write_Cmd_Data (unsigned char x,unsigned int y);
void Write_Data_U16(unsigned int y);
static void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1);
void PutGB1616(unsigned short x, unsigned short y, unsigned int fColor,unsigned int bColor);
void ClearScreen(unsigned int bColor);
void ILI9325_Initial(void);
void lcd_init();
/*******************************************************************/
void main()
{
int_init();
uart_init();
lcd_init();
while(1) ;
}
/*串口中断子程序*/
void interrupt_uart() interrupt 4
{
if(TI)
{
TI = 0 ;
REN = 1;
}
if(RI)
{
RI = 0;
num[conter]=SBUF;
conter++;
if(conter==32)
{
REN=0;
conter = 0;
if(i%12==0)
j=0;
PutGB1616(40+j*16,40+i/12*16,0x0000,0xffff);
i++;
j++;
delayms(500);
SBUF =1;
}
}
}
/*串口初始化*/
void uart_init()
{
SCON = 0x50;//选择串口方式1
TMOD = 0x20;//选择8位自动重装定时方式 方式2
TH1 = 0xfd; //2400bps f4
TL1 = 0xfd;//设置波特率为9600bps
fd
TR1 = 1;
//定时器使能
}
/*中断初始化*/
void int_init()
{
EA = 1;
//总中断
ES =1;
//串口中断
}
/***********************************LCD*****************************/
/*写命令*/
void Write_Cmd(unsigned char DH,unsigned char DL)
{
CS=0;
RS=0;
P1=DH;
RW=0;
RW=1;
P1=DL;
RW=0;
RW=1;
CS=1;
}
/*写数据*/
void Write_Data(unsigned char DH,unsigned char DL)
{
CS=0;
RS=1;
P1=DH;
RW=0;
RW=1;
P1=DL;
RW=0;
RW=1;
CS=1;
}
/*延时*/
void delayms(unsigned int count)
{
int i,j;
for(i=0;i>8;
n=y;
Write_Cmd(0x00,x);
Write_Data(m,n);
}
/*写16位数据*/
void Write_Data_U16(unsigned int y)
{
unsigned char m,n;
m=y>>8;
n=y;
Write_Data(m,n);
}
/*设置位置*/
static void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)
{
Write_Cmd_Data(WINDOW_XADDR_START,x0);
Write_Cmd_Data(WINDOW_XADDR_END,x1);
Write_Cmd_Data(WINDOW_YADDR_START,y0);
Write_Cmd_Data(WINDOW_YADDR_END,y1);
Write_Cmd_Data(GRAM_XADDR,x0);
Write_Cmd_Data(GRAM_YADDR,y0);
Write_Cmd (0x00,0x22);//LCD_WriteCMD(GRAMWR);
}
/*输出字符*/
void PutGB1616(unsigned short x, unsigned short y, unsigned int fColor,unsigned int bColor)
{
unsigned int i,j;
LCD_SetPos(x, x+16-1,y, y+16-1);
for(i=0;i<32;i++)
{
unsigned short m=num[i];
for(j=0;j<8;j++)
{
if((m&0x80)==0x80)
{
Write_Data_U16(fColor);
}
else
{
Write_Data_U16(bColor);
}
m<<=1;
}
}
}
/*清屏*/
void ClearScreen(unsigned int bColor)
{
unsigned int i,j;
//LCD_SetPos(0,240,0,320);//320x240
for (i=0;i<320;i++)
{
for (j=0;j<240;j++)
Write_Data_U16(bColor);
}
}
/*初始化LCD*/
void ILI9325_Initial(void)
{
delayms(50);
Write_Cmd_Data(0x0001,0x0100);
Write_Cmd_Data(0x0002,0x0700);
Write_Cmd_Data(0x0003,0x1030);
Write_Cmd_Data(0x0004,0x0000);
// Write_Cmd_Data(0x0007,0x0030);
Write_Cmd_Data(0x0008,0x0207);
Write_Cmd_Data(0x0009,0x0000);
Write_Cmd_Data(0x000A,0x0000);
Write_Cmd_Data(0x000C,0x0000);
Write_Cmd_Data(0x000D,0x0000);
Write_Cmd_Data(0x000F,0x0000);
//power on sequence VGHVGL
Write_Cmd_Data(0x0010,0x0000);
Write_Cmd_Data(0x0011,0x0007);
Write_Cmd_Data(0x0012,0x0000);
Write_Cmd_Data(0x0013,0x0000);
//vgh
Write_Cmd_Data(0x0010,0x1290);
Write_Cmd_Data(0x0011,0x0227);
//delayms(100);
//vregiout
Write_Cmd_Data(0x0012,0x001d); //0x001b
//delayms(100);
//vom amplitude
Write_Cmd_Data(0x0013,0x1500);
//delayms(100);
//vom H
Write_Cmd_Data(0x0029,0x0018);
Write_Cmd_Data(0x002B,0x000D);
//gamma
Write_Cmd_Data(0x0030,0x0004);
Write_Cmd_Data(0x0031,0x0307);
Write_Cmd_Data(0x0032,0x0002);// 0006
Write_Cmd_Data(0x0035,0x0206);
Write_Cmd_Data(0x0036,0x0408);
Write_Cmd_Data(0x0037,0x0507);
Write_Cmd_Data(0x0038,0x0204);//0200
Write_Cmd_Data(0x0039,0x0707);
Write_Cmd_Data(0x003C,0x0405);// 0504
Write_Cmd_Data(0x003D,0x0F02);
//ram
Write_Cmd_Data(0x0050,0x0000);
Write_Cmd_Data(0x0051,0x00EF);
Write_Cmd_Data(0x0052,0x0000);
Write_Cmd_Data(0x0053,0x013F);
Write_Cmd_Data(0x0060,0xA700);
Write_Cmd_Data(0x0061,0x0001);
Write_Cmd_Data(0x006A,0x0000);
//
Write_Cmd_Data(0x0080,0x0000);
Write_Cmd_Data(0x0081,0x0000);
Write_Cmd_Data(0x0082,0x0000);
Write_Cmd_Data(0x0083,0x0000);
Write_Cmd_Data(0x0084,0x0000);
Write_Cmd_Data(0x0085,0x0000);
//
Write_Cmd_Data(0x0090,0x0010);
Write_Cmd_Data(0x0092,0x0600);
Write_Cmd_Data(0x0093,0x0003);
Write_Cmd_Data(0x0095,0x0110);
Write_Cmd_Data(0x0097,0x0000);
Write_Cmd_Data(0x0098,0x0000);
Write_Cmd_Data(0x0007,0x0133);
Write_Cmd(0x00,0x22);
}
/*LCD初始化*/
void lcd_init()
{
CS=1;
delayms(5);
RES=0;
delayms(5);
RES=1;
delayms(5);
ILI9325_Initial();
ClearScreen(0xf800);
}
参考文献:
1.单片微机原理与接口技术 科学出版社 曾一江 主编
2.C++面向对象的程序设计 清华大学出版社 谭浩强 著
显示屏
UART
UART
蓝牙接收
蓝牙发送
PC端
MCU端
PAGE
2