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-16 20:07

S3C2440串口(1)
1.S3C2440串口概述 串口通讯一般要增加电平转换电路,原因是TTL/CMOS电平与RS232电平不一致: TTL/CMOS电平: CMOS电平: 常用的电平转换芯片是MAX3232。 S3C2440有3个独立的异步串口,可以选择工作在中断或DMA方式下。每个UART包括一个波特率发生器、发送器、接收器和一个控制单元。 UART有FIFO模式和非FIFO模式。FIFO模式下可以利用64字节的发送/接收缓冲寄存器,非FIFO模式下只使用了发送/接收缓冲寄存器中的1个字节。本篇入门级以非FIFO为例。 2.串口设置及相关寄存器 串口引脚是GPIO复用的。本篇UART只用3根引脚:TXD、RXD、GND。 TXD0 – G
[单片机]
51单片机的串口中断设置
首先,你要用软件允许中断, 即C语言中EA = 1; 允许总中断ES = 1; //允许串口中断汇编中可用 SETB EA ;允许总中断 SETB ES ;允许串口中断 当单片机接收到一帧数据后,RI会置1,向CPU申请中断,若之前有中断允许,则产生了中断,进入中断服务程序。 当然,单片机发送完一帧数据,TI也会置1,同样会产生中断! 一般我们在发送数据时要关中断,因为一般你不用在发送时不用处理数据; 接收数据时要开中断,以便你在中断服务程序中将接收到的数据进行存储并处理。 补充:其实,不管你有没有允许中断,上位机(此时即给单片机发送信息的机器)只要给单片机发送数据,单片机就会自动接收数据,并把它放在数据缓冲器S
[单片机]
串口调试助手源程序
1.建立项目 2.在项目中插入MSComm控件 3.利用ClassWizard定义CMSComm类控制变量 4.在对话框中添加控件 5.添加串口事件消息处理函数OnComm() 6.打开和设置串口参数 7.发送数据 8.发送十六进制字符 9.在接收框中以十六进制显示 10.如何设置自动发送 11.什么是VARIANT数据类型?如何使用VARIANT数据类型?   这是串口调试助手源程序及编程详细过程(一)的续篇,首先谢谢朋友们的支持与鼓励。 8.发送十六进制字符 在主对话框中加入一个复选接钮,ID为IDC_CHECK_HEXSEND Captio
[模拟电子]
【跟着江科大学Stm32】GPIO_按键控制LED_光敏传感器控制蜂鸣器
一、按键控制LED 用两个按键来分别控制两个LED的状态,初始状态两灯均熄灭,按下1次点亮,再按下熄灭 因为江科大的套餐抢不到 我就自己看着图和利用现有的东西配了一套,结果是一样的,会比较乱 LED.H #ifndef __LED_H #define __LED_H void LED_Init(void); void LED1_ON(void); void LED1_OFF(void); void LED2_ON(void); void LED2_OFF(void); #endif LED.c #include stm32f10x.h // Device header void LED_
[单片机]
【跟着江科大学Stm32】GPIO_<font color='red'>按键</font>控制LED_光敏传感器控制蜂鸣器
MSP430串口接收程序(使用中断)
使用接收中断,将接收到的字符再发送出去。每次接收到字符之后都会退出低功耗模式,从而在主函数中将接收到的字符再发送出去。 /********************************************** *程序描述:单片机的P3.4、P3.5作为串口接收字符,将接受到的字符再发送出去 *作者 :Zhenhua Liu *时间 :2017.11.02 18:00 ***********************************************/ #include msp430x14x.h void usartInit(void); //串口初始化 void main(v
[单片机]
RS-485串口设备如何升级为CAN接口?
1.概述 由于RS-485 串行通讯存在时间长,设计简单,成本低廉,所以在过去的工业自动化各个行业有着非常广泛的应用,并且在一定程度上还将继续被应用。所以大量的RS-485串行设备存在于生产生活的各种场合。   随着工业的智能化发展,各行业的工业自动化系统对通讯传输的距离、速度、节点数和可靠性等方面的要求都不断的提高,成倍数或者积数的增长。部分的RS-485的设备不得不进行淘汰和升级。   2.什么情况下RS-485串口设备需要升级CAN? 情况一:现有的串口通讯距离不够,或者网络节点容量不够,或增加设备的可靠性和抗干扰性,就需要升级CAN网络。   情况二:上位网络是CAN网络,为了接入上位系统,就需要
[嵌入式]
AT89S52与LCD1602(asm/c51)
LCD1602 DDRAM地址映射表: 第一行地址80H 第二行地址C0H 单片机与LCD1602接口 ;/////////////////////////////////////////////// 项目名称:AT89S52与LCD1602接口实验 功能:在LCD1602的第一行显示WWW.LZY.EDU.CN : 在LCD1602的第二行显示0830--3150897 ;/////////////////////////////////////////////// RS EQUP2.4 ;P2.4接LCD的RS RW EQUP2.5 ;P2.5接L
[单片机]
AT89S52与<font color='red'>LCD1602</font>(asm/c51)
AVR第8课:独立按键
值得注意的是,独立按键的检测原理和消抖处理在51单片机中已经讲过了,这些东西都不会变。只是AVR单片机的IO口操作方式改变了。在AVR中,检测方式是:首先让将和独立按键相连接的IO口设置成输出高电平,接着将他们设置成输入模式,再然后检测这些IO口的值。 代码1:检测是哪一个按键被按下。这里不需要用到消抖动处理。 #include iom16v.h #include macros.h #define uint unsigned int #define uchar unsigned char uchar table = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80}; void
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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