PIC16F887 串口 LCD1602 按键

发布者:TranquilVibes最新更新时间:2020-08-27 来源: eefocus关键字:PIC16F887  串口  LCD1602  按键 手机看文章 扫描二维码
随时随地手机看文章

#include

#include

#include

#include

#define uchar unsigned char

#define uint unsigned int


/* CONFIG1 */

#pragma config FOSC = XT        /* Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) */

#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) */

#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */

#pragma config MCLRE =ON        /* RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD) */

#pragma config CP = OFF         /* Code Protection bit (Program memory code protection is disabled) */

#pragma config CPD = OFF        /* Data Code Protection bit (Data memory code protection is disabled) */

#pragma config BOREN = OFF      /* Brown Out Reset Selection bits (BOR disabled) */

#pragma config IESO = OFF       /* Internal External Switchover bit (Internal/External Switchover mode is disabled) */

#pragma config FCMEN = OFF      /* Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) */

#pragma config LVP = OFF        /* Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) */


/* CONFIG2 */

#pragma config BOR4V = BOR40V   /* Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) */

#pragma config WRT = OFF        /* Flash Program Memory Self Write Enable bits (Write protection off) */



void delaya_US( unsigned char n );



void LCD_CSH( void );



void LCD_WRITE_4( unsigned char R1, unsigned char FLAG );



void LCD_WRITE( unsigned char R1, unsigned char FLAG );



unsigned char LCD_READ( void );



void LCD_BUSY( void );



void delaya( unsigned int n );



/* LCD显示相关 */

#define DATA 1                                       /* LCD写数据时为1 */

#define COM 0                                       /* LCD写命令时为0 */

#define LINE1 0b10000000

#define LINE2 0b11000000


#define LCD_E RD6

#define LCD_RW RD5

#define LCD_RS RD4


/* ======延时(n×10)us */

void delaya_US( unsigned char n )

{

unsigned char j;

for ( j = 0; j < n; j++ )

{

NOP(); NOP();

}

}



/* LCD初始化 */

void LCD_CSH( void )

{

TRISD = 0x00;  /* RD方向输出 */


delaya( 20 );


LCD_WRITE_4( 0b0011, COM );

delaya( 5 );

LCD_WRITE_4( 0b0011, COM );

delaya_US( 10 );

LCD_WRITE_4( 0b0011, COM );

delaya_US( 10 );


LCD_WRITE_4( 0b0010, COM );


LCD_BUSY();

LCD_WRITE( 0b00101000, COM );

LCD_WRITE( 0b00001100, COM );

LCD_WRITE( 0b00000001, COM );

delaya( 2 );

LCD_WRITE( 0b00000110, COM );

}



/* LCD写4位命令 */

void LCD_WRITE_4( unsigned char R1, unsigned char FLAG )

{

LCD_RW = 0; NOP();

LCD_RS = FLAG;

PORTD &= 0xF0;

LCD_E = 1; NOP();

PORTD |= R1;

NOP(); NOP();

LCD_E = 0; NOP();

LCD_RS = 0; NOP();

PORTD &= 0xF0;

}



/* LCD写命令 */

void LCD_WRITE( unsigned char R1, unsigned char FLAG )

{

unsigned char R2;


LCD_BUSY();

LCD_RW = 0; NOP();

LCD_RS = FLAG;

R2 = (R1 >> 4) & 0x0F;

PORTD &= 0xF0; NOP();

LCD_E = 1;

PORTD |= R2;

NOP(); NOP();

LCD_E = 0;


R2 = R1 & 0x0F;

PORTD &= 0xF0; NOP();

LCD_E = 1; NOP();

PORTD |= R2;

NOP(); NOP();

LCD_E = 0; NOP();

LCD_RS = 0; NOP();

PORTD &= 0xF0;

}



/* 读LCD状态 */

unsigned char LCD_READ( void )

{

unsigned char R1;

TRISD = 0x0F;

LCD_RS = 0; NOP();

LCD_RW = 1;

NOP(); NOP();

LCD_E = 1;

NOP(); NOP();

NOP(); NOP();

R1 = 0;

R1 = (PORTD << 4) & 0xF0;

LCD_E = 0;

NOP(); NOP();

NOP(); NOP();

LCD_E = 1;

NOP(); NOP();

R1 |= (PORTD & 0x0F);

LCD_E = 0; NOP();

LCD_RW = 0;

TRISD = 0x00;

return(R1);

}



/* 检测LCD是否忙 */

void LCD_BUSY( void )

{

unsigned char R1;

do

{

R1 = LCD_READ();

}

while ( (R1 & 0x80) == 0x80 );

}



/* ======延时(n)ms */

void delaya( unsigned int n )

{

unsigned int j;

unsigned char k;

for ( j = 0; j < n; j++ )

for ( k = 246; k > 0; k-- )

NOP();

}



/*

 * ***********************************************************************

 * 显示屏字符串写入函数

 * ***********************************************************************

 */

void LCD_write_str( unsigned char x, unsigned char y, char *s )

{

if ( y == 0 )

{

LCD_WRITE( 0x80 + x, COM );

}else {

LCD_WRITE( 0xC0 + x, COM );

}


while ( *s )

{

LCD_WRITE( *s, DATA );

s++;

}

}



#define K1 RC0

#define K2 RC1

int Keyscan( void )

{

TRISC |= 0x03;                   /*按键是输入 */

if ( K1 == 0 )

{

delaya( 5 );

if ( K1 == 0 )

{

while ( K1 == 0 )

;       /* 等待按键松开 */

return(1);

}

}

if ( K2 == 0 )

{

delaya( 5 );

if ( K2 == 0 )

{

while ( K2 == 0 )

;  /* 等待按键松开 */

return(2);

}

}

return(0);

}



/*********************************************************************************

 * 【函 数 名】: void send_cmd(unsigned char dat)

 * 【功    能】: 串口发送数据命令

 **********************************************************************************/

void send( unsigned char dat )

{

TXREG = dat;

while ( TRMT != 1 )

;  /* 等待发送完成 */

}



/*********************************************************************************

 * 【函 数 名】: Print_Str(unsigned char *s)

 * 【功    能】: 串口发送 一个字符串

 **********************************************************************************/

void Print_Str( unsigned char *s )

{

while ( *s != '' )

{

send( *s++ );

}

}


void dispaly_rtctime(unsigned char h,unsigned char m,unsigned char s)

{

    char xianshi[15];

    char count=0;

    xianshi[count++]='0'+h%100/10;

    xianshi[count++]='0'+h%10;

     xianshi[count++]=':';

    xianshi[count++]='0'+m%100/10;

    xianshi[count++]='0'+m%10;

     xianshi[count++]=':';

    xianshi[count++]='0'+s%100/10;

    xianshi[count++]='0'+s%10;

    xianshi[count++]=0;

    LCD_write_str(0,0,xianshi);

}



#define LED RB0


int led_flash = 0;                  /* 为1就闪烁灯定时器闪烁  串口接受会改变这个值 */

unsigned int T1_10MS;                        /* 频率 */

char recdata;                        /* 接受字符 */

char rev_ifg = 0;

char rev_buffer[5];                  /* 装下信息 */

char rev_buffer_count = 0;

int time = 0;    /* 计时 */

char ledifg = 0;

int time1 = 0;

unsigned char rtc_hour = 23;

unsigned char rtc_min = 59;

unsigned char rtc_sec = 55;



void main( void )

{

int key = 0;


ANSEL = 0;                            /*选择ADC引脚 */

ANSELH = 0;


T1CON = 0b00100001;                   /* 内部时钟源 (F OSC /4) */

GIE = 1; PEIE = 1; TMR1IE = 1;

TMR1IF = 0;

T1_10MS = 100;                          /* 执行定时器中断的频率 */

T1_10MS = 1000000 / T1_10MS;            /* 多少时间 也就是选择频率 */

T1_10MS = (65535 - T1_10MS / 4);        /* 给到硬件定时器 */

TMR1H = T1_10MS >> 8;

TMR1L = T1_10MS;

    


/* 串口初始化 */

SPBRG = 25;                           /* 4mhz 9600 */

TXSTA = 0X24;

RCSTA = 0X90;

RCIE = 1;

CREN = 1;

SYNC = 0;

SPEN = 1;

GIE = 1;

PEIE = 1;

TRISC6 = 0;

TRISC7 = 1;

RC6 = 1;

RC7 = 1;


/* 小灯是输出 */

TRISB = 0x00;

LED = 1; /* 输出高 不亮的 */

    

    

    LCD_CSH();

delaya( 30 );

    



while ( 1 )

{

key = Keyscan();        /* key 有按键1或者2 否则就是0 */

if ( key != 0 )

{


led_flash = 0;  /*不再闪烁灯 */

}

        

        

}

}



void interrupt high_isr( void )         /* 也可以加 high_priority */

{

unsigned char xianshi[20];


if ( TMR1IF )                   /* 中断一次 */

{

/* 重新给时间 */

TMR1IF = 0;

TMR1H = T1_10MS >> 8;

TMR1L = T1_10MS;


time1++;

if ( time1 > 100 )

{

time1 = 0; /* 1s时间 */


            //更新时间

rtc_sec++;

if ( rtc_sec == 60 )

{

rtc_sec = 0;

rtc_min++;

if ( rtc_min == 60 )

{

rtc_min = 0;

rtc_hour++;

if ( rtc_hour == 24 )

{

rtc_hour = 0;

}

}

}

            //显示时间

            if(led_flash==0)

            {

                dispaly_rtctime(rtc_hour,rtc_min,rtc_sec);

            }

            

            

}



/*下面就是控制小灯闪烁 */

time++;

if ( time > 10 )

{

time = 0;

if ( led_flash == 1 )

{

ledifg = !ledifg;

if ( ledifg == 0 )

LED = 0;

else LED = 1;

}

}

}  else if ( RCIF )

{

/* 串口接受中断 */

RCIF = 0;

recdata = RCREG;

send( recdata );

        

        if ( rev_ifg == 2 )

{

            rev_buffer[rev_buffer_count++] = recdata;       /* 接受 */

if ( rev_buffer_count == 4 )

{

/* 接受到了4个字符 比如2房3床 就是接收到0203 */

                LCD_CSH();

                delaya( 30 );

LCD_write_str( 0, 0, rev_buffer );      /* 显示出来 */

                

                rev_ifg=0;

[1] [2]
关键字:PIC16F887  串口  LCD1602  按键 引用地址:PIC16F887 串口 LCD1602 按键

上一篇:PICC编译错误
下一篇:PIC18F45K80 CAN通讯示例代码

推荐阅读最新更新时间:2024-11-10 11:55

STM32进阶之串口环形缓冲区实现
队列的概念 在此之前,我们来回顾一下队列的基本概念: 队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。 队列的特点 类似售票排队窗口,先到的人看到能先买到票,然后先走,后来的人只能后买到票 队列的常见两种形式 普通队列 在计算机中,每个信息都是存储在存储单元中的,比喻一下吧,上图的一些小正方形格子就是一个个存储单元,你可以理解为常见的数组,存放我们一个个的信息。 当有大量数据的时候,我们不能存储所有的数据,那么计算机处理数据的时候,只能先处理先来的,那么处理完后呢,就会把数据释放掉,再处理
[单片机]
STM32进阶之<font color='red'>串口</font>环形缓冲区实现
8051单片机串口波特率计算方式
STC12C5A60S2单片机兼容80C51单片机,其串口波特率可以由定时器产生,也可以由独立波特率发生器产生。其波特率模式可以是固定的,也可以是可变的。 固定波特率:当 模式0的通信速度设置 位UART_M0x6/AUXR.5 = 0时,其波特率 = SYSclk/12 当 模式0的通信速度设置 位UART_M0x6/AUXR.5 = 1时,其波特率 = SYSclk/2 可变波特率:使用串行通信模式2,即可自定义串口通信波特率,其计算公式为:波特率 = 2^SMODE /64×( SYSclk 系统工作时钟频率) 当SMOD=1时,波特率=2/64( SYSclk) =1/32( SYSclk) ; 当SMOD
[单片机]
51单片机学习:串口通信实验
实验名称:串口通信实验 接线说明: 实验现象:下载程序后,当串口助手发送数据给单片机,单片机原封不动转发给串口助手显示 注意事项:使用黄色跳线帽将CH340旁的P5端子的UTX和P30短接,URX和P31短接,出厂默认已短接好 ***************************************************************************************/ #include reg52.h typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; /***************************
[单片机]
DS18b20在Atmega8下的编程,串口通信电脑显示
=****************************************************** MCU:Atmega8 内部振荡器:8M 环境:ICCAVR 7.0 程序:sdyzxue 薛海涛 2010/06/16 =******************************************************* #include macros.h #include iom8v.h #define fosc 8000000 #define baud 9600 #define SEI() asm( sei ) #define CLR_DIR_1WIRE DDRC&=~BIT(1)
[单片机]
labview实现串口通信(二)
labview也可以调用mscomm控件来实现串口通信,但是编程相对来讲比较复杂,一般不推荐,直接用labview中自带的visa是最方便的,在调试过程中的注意事项, 一、串口通讯的波特率设置要精确,比如要求9600的波特率,则晶振应选择11.0593MHz或其倍数。 二、由于通常情况下LabVIEW串口VI接收或发送的都是字符串(Normal), 这里是指串口通信中,如果不是在串口通信,我们可以做个小小的验证, 在前面板中,字符串在正常显示的情况下,你输入00,跟字符串00也会匹配,指示灯也会亮的,但是在串口通信中,一定注意, 所以如果需要发送或接收十六进制数值(Hex),请在发送或接收之前进行必要的转换。(这一点尤
[测试测量]
PIC16C5X单片机模拟串口的源程序
TITLE TWO WIRE/I2C BUS INTERFACE WITH PIC16C5x ; LIST P=16C54 ; ;***************************************************************************** ;** Two wire/I2C Bus READ/WRITE Sample Routines of Microchip's ;** 24Cxx / 85Cxx serial CMOS EEPROM interfacing to a ;** PIC16C54 8-bit CMOS single chip microcomputer ;*
[单片机]
基于51单片机+LCD1602显示
LCD1602介绍 LCD1602相关引脚 LCD1602写命令、写数据相关操作图 根据上面时序图和时序参数图我们可以写出 写命令代码 和写数据代码 写命令 代码 写命令 void write_com(char command) { RS = 0; RW = 0; //高读低写 LCD = command; delay5ms(); //这里延时最低要30纳秒 我们直接给5ms E = 1;//使能拉高 delay5ms(); //最低要求延迟150纳秒 我们直接给5ms E = 0; } 写数据 代码 写数据 void write_data(char data) {
[单片机]
基于51单片机+<font color='red'>LCD1602</font>显示
单片机驱动矩阵按键与独立按键源代码
本程序所用的原理图下载: 点这里 ,单片机芯片使用的stc89c52;找到相应部分即可.这是一整个单片机开发板的电路图其他的忽略. hex文件及其工程文件下载:http://www.51hei.com/f/pingfc.rar 下面是程序源码: /* *功能:使用矩阵按键使得按键按下时数码管上显示各自对应的数字的立方数 * 优化显示,只显示有效位; * 且使用独立按键实现key1清零,key2加数,key3减数; *日期:2013-05-07-10:20 *作者:徐冉 *特别说明:本程序代码已经通过调试,仅供学习使用; * */ /***********AT89C52-RC 单片机-51hei实验板***********/
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved