从单片机到嵌入式开发

您所在的位置:网站首页 单片机常用显示器 从单片机到嵌入式开发

从单片机到嵌入式开发

#从单片机到嵌入式开发| 来源: 网络整理| 查看: 265

此前我们已经对单片机的基本功能有了一定的了解,接下来我们介绍一下几款常见的单片机外部设备。首先是常用的LCD显示屏模块,此处选用LCD1602(器件名LM016L)进行介绍。然后是AD转换的部分,这里选择并行的ADC0808和DAC0808进行介绍。最后介绍一个使用I2C通信协议的AT24C1024外置EEPROM模块。 以上几种模块都是比较常见的外设组件。在此仅对各个模块做一个简单的介绍,并给出一套简单的例程示范。详细的使用方法请参考相应器件的数据手册。

LCD显示屏 LCD1602 TEST 如图为LCD1602显示屏,驱动一个LCD1602显示屏需要一个并行数据口data,数据/指令信号RS,读/写信号RW,使能信号E。 LCD1602的基本动作如下: static void Wait(void) //忙检测函数,最高位是0允许执行,1等待 { unsigned char sta = 0; data = 0xff; rs = 0; // 选择发送命令模式 rw = 1; // 选择读取模式 do{ en = 1; sta = data; en = 0; //使能,用完就拉低,释放总线 }while(sta & 0x80); } void Write(unsigned char rsc,unsigned char cmd) //写指令/数据函数,rsc是0写入指令,1写入数据 { Wait(); // 先等待LCD1602处于不忙状态 en = 0; // 禁止LCD rs = rsc; // 选择发送模式 rw = 0; // 选择写入模式 data = cmd; // 写数据 en = 1; // 使能LCD en = 0; // 禁止LCD }

具体使用流程如下: 首先,进行LCD1602初始化。

void Init() { Write(0, 0x38); // 按照数据手册,发送38H delay5ms(); // 延时5ms Write(0, 0x38); // 按照数据手册,发送38H delay5ms(); // 延时5ms Write(0, 0x38); // 按照数据手册,发送38H delay5ms(); // 延时5ms Write(0, 0x38); // 显示模式设置 Write(0, 0x08); // 关闭显示 Write(0, 0x01); // 清屏(同时清数据指针) Write(0, 0x06); // 读写后指针自动加1 Write(0, 0x0c); // 开显示,不显示光标 }

此部分主要是按照初始化时序输入指令进行初始化,以及模式设置,然后就可以进行字符串显示了。

void SetCursor(unsigned char x, unsigned char y) //设置坐标,LCD1602的坐标地址为第一行0x80-0x8f,第二行0xc0-0xcf { Write(0, 0x80 + 0x40*y + x); } void ShowStr(unsigned char x, unsigned char y, unsigned char *pStr) //在指定坐标显示字符串 { SetCursor(x, y); //设置起点的坐标 while (*pStr != '\0'){ Write(1, *pStr++);//自增写数据 } }

带字库的LCD12864使用方法与之类同,基本硬件操作部分与上述代码可以复用。LCD12864多一个串/并控制口PSB。 LCD12864初始化、光标控制、写数据指令如下:

void Init() { psb = 1; Write(0, 0x34); // 扩充指令操作 delay5ms(); // 延时5ms Write(0, 0x30); // 基本指令操作 delay5ms(); // 延时5ms Write(0, 0x0c); // 开显示,不显示光标 delay5ms(); // 延时5ms Write(0, 0x01); // 清屏(同时清数据指针) } void SetCursor(unsigned char x, unsigned char y) //设置坐标,LCD12864的坐标地址为0x80 0x90 0x88 0x98 { Write(0, 0x80 + y>1?0x08:0x00 + y%2?0x10:0x00 + x); } void ShowStr(unsigned char x, unsigned char y, unsigned char *pStr) //在指定坐标显示字符串 英文字符占半位 汉字占整位 自增 { SetCursor(x, y); //设置起点的坐标 while (*pStr != '\0'){ Write(1, *pStr++);//自增写数据 } }

2.AD/DA转换 ADC0808 如图为ADC0808模数转换芯片,驱动一个ADC0808模数转换芯片需要一个并行数据口data,启动信号ST,不高于640KHz的时钟信号CLK,同时监听转换完成信号EOC。ADC0808芯片的使用流程为:在脉冲信号CLK的驱动下,给ST一个正脉冲信号,则AD转换开始,等到EOC信号转为正,则转换结束,OUT1-8口自高向低输出数据(注意OUT1为最高位)。返回值为0-255,对应ADC输入的参考电平VREF-和VREF+,实际电压值将0-255等比变换至所需的电压区间即可。比如此题中测量电压为0-5V,则对应电压值为测量值/255*5(V)=测量值/51(V)。

unsigned char getdata() { unsigned char data; st = 0; st = 1; st = 0; oe = 0; while(!eoc); P1 = 0xFF; oe = 1; data = P1; oe = 0; return data; }

DAC0808

将读取的数据通过P3端口送到DAC0808,经运算放大器处理后可以看见输出电压,因为输出电压范围为0-10V,故可看见输出电压约为输入电压值的两倍。

I2C+EEPROM I2CEEPROM 如图为AT24C1024外置存储设备的使用。AT24C1024是一个1024K大小的串行EEPROM,通过I2C协议进行读写,使用SCL、SDA端口。WP用于写保护开关,为1开启写保护,A1用于硬件地址选择,默认为0,可以与其他芯片连接。下面我将给出该设备的使用代码,并进行解释。 首先是I2C通信协议所需要的部分。I2C协议需要的函数有如下几个:void Start_I2c(); 总线启动函数,用于启动I2C通信void Stop_I2c(); 总线终止函数,用于结束I2C通信void sendByte(unsigned char c); 数据发送函数,发单个字符数据unsigned char RcvByte(); 数据接收函数,收单个字符数据void Ack_I2c(void); 应答子函数,表示数据成功接收void NoAck_I2c(void); 非应答子函数,通知设备结束发送 此外还需要一个全局接收标志符ack,作为应答标志。 //启动总线 void Start_I2c() { SDA=1; //发送起始条件的数据信号 _Nop(); SCL=1; //SCL保持高电平,总线开启 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); //5周期延时 SDA=0; //SDA负跳变,表示起始信号 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); //5周期延时 SCL=0; //暂停I2C总线,准备接收操作 _Nop(); _Nop(); //2周期延时 } //结束总线 void Stop_I2c() { SDA=0; //发送结束条件的数据信号 _Nop(); SCL=1; //SCL保持高电平,总线开启 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); //5周期延时 SDA=1; //SDA正跳变,表示结束信号 _Nop(); _Nop(); _Nop(); _Nop(); //4周期延时,结束 } //字节数据传送函数 void sendByte(unsigned char c) { unsigned char BitCnt; for(BitCnt=0;BitCnt unsigned char retc; unsigned char BitCnt; retc=0; //数据接收临时变量 SDA=1; //数据线置位,准备接收 for(BitCnt=0;BitCnt SDA=0; //发送结束条件的数据信号 _Nop(); _Nop(); _Nop(); //3周期延时 SCL=1; //SCL保持高电平,总线开启 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); //5周期延时 SCL=0; //暂停I2C总线,准备接收操作 _Nop(); _Nop(); //2周期延时 } //非应答信号 void NoAck_I2c(void) { SDA=1; //数据线置位 _Nop(); _Nop(); _Nop(); //3周期延时 SCL=1; //SCL保持高电平,总线开启 _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); //5周期延时 SCL=0; //暂停I2C总线,准备接收操作 _Nop(); _Nop(); //2周期延时 }

以上就是I2C总线通讯的基本操作函数,_Nop()为空指令函数,表示延时一个周期。使用时遵循启动-发送-结束或者启动-接收-应答函数-结束即可。 下面是AT24C1024使用I2C的处理函数。AT24C1024使用到的函数如下:

数据发送函数bit mcu_sendByte( unsigned char add, unsigned char dat); 参数add:地址,dat:数据;返回值:成功/失败。字符串发送函数bit mcu_send_string( unsigned char add, unsigned char rom_add_h, unsigned char rom_add_l, unsigned char *s, unsigned char num); 参数add:地址,rom_add:rom高/低地址,s:字符串,num:字符位数;返回值:成功/失败。数据接收函数bit mcu_RcvByte( unsigned char add, unsigned char *c); 参数add:地址,c:接收数据地址;返回值:成功/失败。字符串接收函数bit mcu_receive_string( unsigned char add, unsigned char rom_add_h, unsigned char rom_add_l, unsigned char *s, unsigned char num); 参数add:地址,rom_add:rom高/低地址,s:字符串,num:字符位数;返回值:成功/失败。 //器件当前地址写字节数据 bit mcu_sendByte(unsigned char add, unsigned char dat) { Start_I2c(); //I2C开始 sendByte(add); //写器件地址 if(ack==0) return 0; sendByte(dat); //如果应答,则发送数据 if(ack==0) return 0; Stop_I2c(); //正常结束,返回1 return 1; } //向器件指定地址写字符串 bit mcu_send_string(unsigned char add,unsigned char rom_add_h,unsigned char rom_add_l,unsigned char *s,unsigned char num) { unsigned char i; Start_I2c(); //I2C开始 sendByte(add); //写器件地址 if(ack==0) return 0; sendByte(rom_add_h); //如果应答,发地址高8位 if(ack==0) return 0; sendByte(rom_add_l); //如果应答,发地址低8位 if(ack==0) return 0; for(i=0;i Start_I2c(); //I2C开始 sendByte(add); //写器件地址 if(ack==0) return 0; *c=RcvByte(); //如果应答,则读取数据 NoAck_I2c(); //送非应答信号 Stop_I2c(); //正常结束,返回1 return 1; } //从器件指定地址读字符串 bit mcu_receive_string(unsigned char add,unsigned char rom_add_h,unsigned char rom_add_l,unsigned char *s,unsigned char num) { unsigned char i; Start_I2c(); //I2C开始 sendByte(add); //写器件地址 if(ack==0) return 0; sendByte(rom_add_h); //如果应答,发地址高8位 if(ack==0) return 0; sendByte(rom_add_l); //如果应答,发地址低8位 if(ack==0) return 0; Start_I2c(); //I2C重新开始 sendByte(add+1); //写器件地址,方式为读 if(ack==0) return 0; for(i=0;i


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3