辜渝傧

13037102709

027-87870986

教学实训

您当前的位置:首页 > 教学资源 > 实训方案 >

无线传感网络实训|实验3.1 IIC控制OLED实验

发布者:唯众    布时间:2020-11-27 15:36:33    点击量:

1.实验目的

1)、通过实验掌握CC2530芯片GPIO模拟IIC的方法
2)、掌握模拟IIC驱动OLED的能力

2.实验设备

硬件:PC机1台、ZIGBEE节点板1套(底板、核心板、仿真器、USB 线)
软件:2000/XP/win7 系统,IAR 8.10 集成开发环境

3.实验相关电路图

实验3.1 IIC控制OLED实验

4.实验相关寄存器

5.源码分析

#include <ioCC2530.H>
#include <string.h>
#include <stdio.h>
 
#include "ASCII_CODE_8X16_5X8_VERTICAL.H"
#include "Chinese_And_Graphic.H"
 
//======================================================
#define lcd_scl  P0_4           //接口定义:lcd_sclk就是LCD的SCL  
#define lcd_sda  P0_5         //接口定义:lcd_sda就是LCD的SDA 
 
 
#define BV(x)     (1<<x)
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
 
//延时函数
void Delay_us() //1 us延时
{
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");   
    asm("nop");
    asm("nop");
    asm("nop");    
    asm("nop");
}
 
void Delay3us()  
{
       Delay_us();
       Delay_us();
       Delay_us();
}
 
void Delay_1ms(void)       //1 ms延时
{
       unsigned int i;
       for(i=0;i<1000;i++)
              Delay_us();
}
 
void Delay_ms(uint ms)
{
       for(uint i=0;i<ms;i++)
              Delay_1ms();
}     
      
void  start()
{
       lcd_scl = 1;
       lcd_sda = 1;
       lcd_sda=0;
       lcd_scl=0;
}
 
void  stop()
{
       lcd_scl=0;
       lcd_sda=0;
       lcd_sda=1;
       lcd_scl=1;
}
 
//传8位指令或数据到OLED显示模块
void transfer(uchar data1)
{
       unsigned char j;
       for(j=0;j<8;j++)
       {
              lcd_scl=0;     
              if(data1&0x80)    lcd_sda=1; 
              else             lcd_sda=0; 
              data1<<=1;
              lcd_scl=1;
    }
    lcd_scl=0;
    Delay3us();  //   ACK时间
    lcd_scl=1;
}
 
//写指令到OLED显示模块
void transfer_command(uchar com)  
{
       start();
       transfer(0x78);
       transfer(0x00);
       transfer(com);
       stop();
}
 
//写数据到OLED显示模块
void transfer_data(uchar dat)
{
       start();
       transfer(0x78);
       transfer(0x40);
       transfer(dat);
       stop();
}
 
 
//OLED显示模块初始化
void initial_lcd()
{     
       Delay_ms(200);
      
       transfer_command(0xae);       //关显示
      
       transfer_command(0xd5);       //晶振频率
       transfer_command(0x80);
      
       transfer_command(0xa8);       //duty设置
       transfer_command(0x1f); //duty=1/32
      
       transfer_command(0xd3);       //显示偏移
       transfer_command(0x00);      
      
       transfer_command(0xa1);       //段重定向设置
       transfer_command(0xa6);
       transfer_command(0x40);       //起始行
       transfer_command(0xb0);
       transfer_command(0xd5);      
       transfer_command(0xf0);
      
      
       transfer_command(0x8d);       //升压允许
       transfer_command(0x14);      
      
       transfer_command(0x20);       //page address mode
       transfer_command(0x02);
      
       transfer_command(0xc8); //行扫描顺序:从上到下
       transfer_command(0xa1); //列扫描顺序:从左到右
      
       transfer_command(0xda); //sequential configuration
       transfer_command(0x02);       //****************
      
       transfer_command(0x81); //微调对比度,本指令的0x81不要改动,改下面的值
       transfer_command(0xcf); //微调对比度的值,可设置范围0x00~0xff
      
      
       transfer_command(0xd9); //Set Pre-Charge Period
       transfer_command(0xf1);
      
       transfer_command(0xdb); //Set VCOMH Deselect Level
       transfer_command(0x49);
      
       transfer_command(0xaf); //开显示
}
 
void lcd_address(uchar page,uchar column)
{
       column=column-1;                                             //我们平常所说的第1列,在LCD驱动IC里是第0列。所以在这里减去1.
       page=page-1;
       transfer_command(0xb0+page);                          //设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1
       transfer_command(((column>>4)&0x0f)+0x10);       //设置列地址的高4位
       transfer_command(column&0x0f);                            //设置列地址的低4位
}
 
//全屏清屏
void clear_screen()
{
       unsigned char i,j;
      for(j=0;j<8;j++)
       {
              lcd_address(1+j,1);
              for(i=0;i<128;i++)
              {
                     transfer_data(0x00);
              }
       }
}
 
//full display test
void full_display(uchar data1,uchar data2)
{
       int i,j;
       for(i=0;i<8;i++)
       {
              lcd_address(i+1,1);
              for(j=0;j<64;j++)
              {
                     transfer_data(data1);
                     transfer_data(data2);                             
              }
       }         
}
 
//显示128x32点阵的图片
void display_128x32(uchar page,uchar column,uchar *dp)
{
       uint i,j;
       for(j=0;j<4;j++)
       {
              lcd_address(page+j,column);
              for (i=0;i<128;i++)
              {     
                     transfer_data(*dp);                                //写数据到LCD,每写完一个8位的数据后列地址自动加1
                     dp++;
              }
       }
}
 
//显示单个32x32点阵图像、汉字、生僻字或32x32点阵的其他图标
void display_graphic_32x32(uchar page,uchar column,uchar *dp)
{
       uchar i,j;
       for(j=0;j<4;j++)
       {
              lcd_address(page+j,column);
              for (i=0;i<32;i++)
              {     
                     transfer_data(*dp);           //写数据到LCD,每写完一个8位的数据后列地址自动加1
                     dp++;
              }
       }
}
 
//显示单个16x16点阵图像、汉字、生僻字或16x16点阵的其他图标
void display_graphic_16x16(uchar page,uchar column,uchar *dp)
{
       uchar i,j;
       for(j=0;j<2;j++)
       {
              lcd_address(page-1,column);
              for (i=0;i<16;i++)
              {     
                     transfer_data(*dp);           //写数据到LCD,每写完一个8位的数据后列地址自动加1
                     dp++;
              }
       }
}
 
//显示单个8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标
void display_graphic_8x16(uchar page,uchar column,uchar *dp)
{
       uchar i,j;
       for(j=0;j<2;j++)
       {
              lcd_address(page+j,column);
              for (i=0;i<8;i++)
              {     
                     transfer_data(*dp);                                //写数据到LCD,每写完一个8位的数据后列地址自动加1
                     dp++;
              }
       }
}
 
//显示8x16的点阵的字符串,括号里的参数分别为(页,列,字符串指针)
void display_string_8x16(uint page,uint column,uchar text[])
{
       uint i=0,j,k,n;
       if(column>123)
       {
              column=1;
              page+=2;
       }
       while(text[i]>0x00)
       {     
              if((text[i]>=0x20)&&(text[i]<=0x7e))
              {
                     j=text[i]-0x20;
                     for(n=0;n<2;n++)
                     {                   
                            lcd_address(page+n,column);
                            for(k=0;k<8;k++)
                            {                                 
                                   transfer_data(ascii_table_8x16[j][k+8*n]);  //写数据到LCD,每写完1字节的数据后列地址自动加1
                            }
                     }
                     i++;
                     column+=8;
              }
              else
                     i++;
       }
}
 
 
 
//显示5x8的点阵的字符串,括号里的参数分别为(页,列,字符串指针)
void display_string_5x8(uint page,uint column,uchar reverse,uchar *text)// 5,1,0  不反显
{                                                                                                                             // 5,1,1  反显
       uint i=0,j,k,disp_data;
       while(text[i]>0x00)
       {     
              if((text[i]>=0x20)&&(text[i]<=0x7e))
              {
                     j=text[i]-0x20;
                     lcd_address(page,column);
                     for(k=0;k<5;k++)
                     {
                            if(reverse==1)
                            {
                                   disp_data=~ascii_table_5x8[j][k];
                            }
                            else
                            {
                                   disp_data=ascii_table_5x8[j][k];
                            }
                           
                            transfer_data(disp_data); //写数据到LCD,每写完1字节的数据后列地址自动加1
                     }
                     if(reverse==1)      transfer_data(0xff);    //写入一列空白列,使得5x8的字符与字符之间有一列间隔,更美观
                     else transfer_data(0x00);                //写入一列空白列,使得5x8的字符与字符之间有一列间隔,更美观
                     i++;
                     column+=6;
                     if(column>123)
                     {
                            column=1;
                            page++;
                     }
              }
              else
                     i++;
       }
}
 
 
//写入一组16x16点阵的汉字字符串(取模的点阵数据数组中需含有此字)
//括号里的参数:(页,列,汉字字符串)
void display_string_16x16(uchar page,uchar column,uchar *text)
{
    uchar i,j,k;
    uint address;
   
    j = 0;
    while(text[j] != '\0')
    {
        i = 0;
        address = 1;
        while(Chinese_text_16x16[i] > 0x7e)    // >0x7f即说明不是ASCII码字符
        {
            if(Chinese_text_16x16[i] == text[j])
            {
                if(Chinese_text_16x16[i + 1] == text[j + 1])
                {
                    address = i * 16;
                    break;
                }
            }
            i += 2;           
        }
       
        if(column > 113)
        {
            column = 0;
            page += 2;
        }
       
        if(address != 1)// 显示汉字                  
        {
           
                     for(k=0;k<2;k++)
                     {
                            lcd_address(page+k,column);
                   for(i = 0; i < 16; i++)              
                   {
                       transfer_data(Chinese_code_16x16[address]);  
                       address++;
                   }
                  }
            j += 2;       
        }
        else              //显示空白字符           
        {
                     for(k=0;k<2;k++)
                     {
                            lcd_address(page+k,column);
                   for(i = 0; i < 16; i++)              
                   {
                       transfer_data(0x00);  
                   }
                  }
           
            j++;
        }
       
        column+=16;
    }
}
 
 
//显示16x16点阵的汉字或者ASCII码8x16点阵的字符混合字符串
//括号里的参数:(页,列,字符串)
void disp_string_8x16_16x16(uchar page,uchar column,uchar *text)
{
    uchar temp[3];
    uchar i = 0;   
   
    while(text[i] != '\0')
    {
        if(text[i] > 0x7e)
        {
            temp[0] = text[i];
            temp[1] = text[i + 1];
            temp[2] = '\0';          //汉字为两个字节
            display_string_16x16(page,column,temp);  //显示汉字
            column += 16;
            i += 2;
        }
        else
        {
            temp[0] = text[i];   
            temp[1] = '\0';          //字母占一个字节
            display_string_8x16(page, column, temp);  //显示字母
            column += 8;
            i++;
        }
    }
}
static void port_init( void )
{     
       P0SEL &= ~BV(5);                     //General-purpose I/O
       P0DIR |= BV(5);                        //OutPut
      
       P0SEL &= ~BV(4);                     //General-purpose I/O
       P0DIR |= BV(4);                        //OutPut
      
       lcd_sda = 1;
       lcd_scl = 1;
}
 
void clock_setup(void)
{
       CLKCONCMD &= ~0x40;                         //设置系统时钟源为32MHZ晶振
    while(CLKCONSTA & 0x40);                    //等待晶振稳定
    CLKCONCMD &= ~0x47;                         //设置系统主时钟频率为32MHZ
}
 
void main(void)
{
       port_init();
       initial_lcd();                                                                 //初始化                          
       clock_setup();
      
       while(1)
       {
        clear_screen();                                                          //清屏
              disp_string_8x16_16x16(1,1,"武汉唯众智创科技");             //显示字符串,括号里的参数分别为(PAGE,列,字符串指针)
              disp_string_8x16_16x16(3,1,"Coming on 123!!");     //显示16x16点阵汉字串或8x16点阵的字符串,括号里的参数分别为(页,列,字符串指针)
              Delay_ms(1000);
       }
}

6.实验现象

       蓝色OLED第一行显示“武汉唯众智创科技”,第二行显示“Coming on 123!”。汉字和英文字符数字都是可以显示的,并且每秒刷新(闪烁)一下。补充说明一下,该OLED不带字库,显示所有的字符都需要使用取模软件提取。
实验3.1 IIC控制OLED实验实验3.1 IIC控制OLED实验


上一篇:无线传感网络实训|第三章 传感器实验介绍

下一篇:无线传感网络实训|实验3.2 传感器编号实验