2014-04-12 08:49:45 greatwall_sdut 阅读数 3447
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏
/*
* 跑马灯程序,做单片机的第一个小程序,相当于软件开发中的hello world
* 可实现led灯循环移动
* 通过P1口的8个引脚控制8个led灯的亮灭。
* 滨州学院信息技术研发中心 孙继磊  2014-4-11
*/
#include <reg52.h>
unsigned char  rotate(unsigned char n);
void main(void)
{    
	unsigned int j;
	unsigned char i=0xf0,k=0xf0;
	while(1)
	{ 
	  P1 = i;             //为p1口赋值(即相当于给8个引脚赋值)
	  for(j=0;j<40000;j++);//延时,保持当前灯亮状态一段时间,使人眼能够观察得到
	  i=rotate(i);         //循环右移
    }
}
//循环右移一位
unsigned char  rotate(unsigned char n)
{
    unsigned char t ;
    t = n & 1;		//取最低位
    n = n>>1;
    if(t) n = n | 0x80;
    return n;
}



2016-11-01 19:32:06 Code_star_one 阅读数 6823
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

通过一位 F 的16进制 转换为 2进制的 1111 然后移动一位 有三极管开关所改变。0的时候发光,1的时候变暗。所以一开始0FFH表示高8位为0;
低8位为1111 1111,表示全暗,然后右移变为1111 1110亮第一个等。
之后类推。实现了跑马灯。

    ORG     0000H
    AJMP    MAIN
    ORG     0030H
MAIN:
    MOV     A,#0FFH 
    CLR     C       
    MOV     R2,#08H 

LOOP1:  
    RLC     A       /*左移一位*/
    MOV     P0,A    
    ACALL   DEL     
    DJNZ    R2,LOOP1    
    MOV     R2,#08H 

LOOP2:  
    RRC     A       /*右移一位*/
    MOV     P0,A    
    ACALL   DEL 
    DJNZ    R2,LOOP2    
    JMP     MAIN    


DEL:    MOV R5,#05H    /*这是一个延时函数*/
DEL1:   MOV R6,#0F0H
DEL2:   MOV R7,#0F0H
DEL3:   DJNZ R7, DEL3
    DJNZ R6, DEL2
    DJNZ R5, DEL1
    RET
END
2017-10-26 20:51:37 qq_35576988 阅读数 455
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

原理分析:什么是跑马灯

(1)跑马灯和流水灯非常像,不同的是:流水灯是8颗LED其中7灭1亮,亮的在移动;跑马灯是8颗LED7亮1灭,灭的在移动。
   01111111 0x7f 10000000
  10111111 0xbf 01000000
  11011111 0xdf 00100000


(2)编程实现跑马灯,必须用到C语言的2种技巧:左移(右移)、按位取反;
          C语言中~这个符号表示对一个数字按位取反,譬如一个数01111111按位取反后变成了10000000。而11011111按位取反后变成了00100000

          相反 01 左移


例程:

#include<reg51.h>




void delay(void)
{
   unsigned char i = 100;
   unsigned char j = 100;
   while(i--)
   {
     while(j--);
}
} //延时函数


void main(void)
{  
     unsigned char i = 0;
unsigned char initial_value = 0x80;
     while(1)
{
  
       for(i = 0; i < 8; i++)
  {
  P0 = ~(initial_value>>i);
  delay();
  }


}


}  

2017-09-05 20:32:15 Allenge16 阅读数 554
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

流水灯来回跑


#include<reg52.h>


void delay(unsigned int t);




void main()
{
    unsigned char i;
    delay(20000);
while (1)
{
for(i=0;i<8;i++)
{
  P2 = ~(0x01<<i);
  delay(20000);
}
for(i=0;i<7;i++)
{
  P2 = ~(0x80>>i);
  delay(20000);
}
}

}
void delay(unsigned int t)
{
while(t --);
}

2019-07-27 19:39:06 jinwe888 阅读数 125
  • 单片机控制第一个外设-LED-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

初始学习单片机,LCD1602的滚动只能实现2行同时移动,就改了哈,写了个滚动的程序。在测试的时候发现了一个问题,在学习板上能正常运行的代码放到Proteus上问题出错,不能正常显示,最后在网上搜索原因时发现可能是Proteus仿真时对端口有要求,最后将商品修改到PORTB和PORTD就正常了。

这是显示效果https://v.youku.com/v_show/id_XNDI5MDEwOTg4NA==.html?spm=a2h3j.8428770.3416059.1

原理图

 

LCD1602.c

//---------------------------------------------------------------
//LCD1602液晶控制与显示程序
//---------------------------------------------------------------

#include <pic.h>
#include <string.h>
#include <stdio.h>
#include "LCD1602.h"

//---------------------------------------------------------------
//LCD忙等待
//---------------------------------------------------------------
void LCD_BUSY_WAIT()
{
    INT8U status;
    TRIS_LCD_DAT=0xFF;                       //将端口设为输入
    RS=0;RW=1;                               //读寄存器状态
    do
    {
        E=1;NOP();status=PORT_LCD_DAT;E=0;   //读取忙信号
    }while(status & 0x80);                   //如果为0x80就是忙,继续进入循环
}

//----------------------------------------------------------------
//写LCD命令
//----------------------------------------------------------------
void Write_LCD_Command(INT8U cmd)
{
    TRIS_LCD_DAT=0x00;                       //LCD数据端口设为输出
    PORT_LCD_DAT=cmd;                        //发送命令
    PORT_LCD_CTL=TRIS_LCD_CTL=0x00;          //控制端口设为输出,初值为0x00
    RS=0;RW=0;E=1;NOP();E=0;                 //写命令
    LCD_BUSY_WAIT();                         //LCD忙等待
}

//----------------------------------------------------------------
//写LCD数据寄存器
//----------------------------------------------------------------
void Write_LCD_Data(INT8U dat)
{
    TRIS_LCD_DAT=0x00;                       //LCD数据端口设为输出
    PORT_LCD_DAT=dat;                        //发送数据
    RS=1;RW=0;E=1;NOP();E=0;                 //写数据
    LCD_BUSY_WAIT();                         //LCD忙等待
}

//----------------------------------------------------------------
//LCD初始化
//----------------------------------------------------------------
void LCD_Initialize()
{
    Write_LCD_Command(0x38);__delay_ms(2);    //置功能,8位,双行,5*7
    Write_LCD_Command(0x01);__delay_ms(2);    //清屏
    Write_LCD_Command(0x06);__delay_ms(2);    //字符进入模式:屏幕不动,字符后移
    Write_LCD_Command(0x0c);__delay_ms(2);    //显示开,关光标
}
//----------------------------------------------------------------
//在r行(0-1) C列(0-15)显示字符串
//----------------------------------------------------------------
void LCD_ShowString(INT8U r,INT8U c,char *str)
{
    INT8U i=0;
    //设置字符地址,第一行首地址为0x80,第二行首地址为0xc0
    if(r==0) Write_LCD_Command(0x80 | c);else
        if(r==1) Write_LCD_Command(0xc0 | c);
    
    //从字符串的第一个字符车起,如果大于16个字符或者碰到'\0'结束
    for(i=0;i<16 && str[i]!='\0';i++)
        Write_LCD_Data(str[i]);                //循环写入字符,地址自动增加
}

//----------------------------------------------------------------
//滚动显示字符串
//----------------------------------------------------------------
void LCD_ScrolShow(INT8U r,INT8U c,char *str)
{
    char tmp[]="                ";            //定义空字符串
    char tmp1[]="                ";
    INT8U k=0;
    INT8U len=strlen(str)-1;                  //字符总长度
    
//  循环显示
    do
    {
        LCD_ShowString(r,c,tmp);
        CopyString(tmp,str,k++);
        __delay_ms(500);
    }while(len--);
    
    //全部显示完后再显示16个空格,实现滚动
    for(k=0;k<16;k++)
    {
        CopyString(tmp,tmp1,k);
        LCD_ShowString(r,c,tmp);
        __delay_ms(500);
    }
}

//-----------------------------------------------------------------
//拷贝字符串来实现滚动 ds目标字符串,ss源字符串,c每次拷贝一个
//-----------------------------------------------------------------
void CopyString(char *ds,char *ss,INT8U c)
{
    INT8U i;
    
    for(i=0;i<16;i++)
    {
        ds[i]=ds[i+1];          //字符依次向前进一个
    }
   
    ds[i-1]=ss[c];             //加入新字符 
    ds[i]='\0';
}

LCD1602.h 

/* 
 * File:   LCD1602.h
 * Author: 5510
 *
 * Created on 2019年7月16日, 下午10:29
 */

#ifndef LCD1602_H
#define	LCD1602_H

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef	__cplusplus
}
#endif

#endif	/* LCD1602_H */

#define INT8U unsigned char
#define INT16U unsigned char
#define _XTAL_FREQ 4000000UL            //定义晶振为4M

#define LCD_CLS           0x01          //清屏
#define LCD_HOME          0x02          //光标移到左上角
#define LCD_SETMODE       0x04
#define LCD_SETVISIBLE    0x08
#define LCD_SHIFT         0x10
#define LCD_SETFUNCTION   0x20
#define LCD_SETCGADDR     0x40
#define LCD_SETDDADDR     0x80

//仿真用端口定义
#define PORT_LCD_DAT      PORTB
#define PORT_LCD_CTL      PORTD
#define TRIS_LCD_DAT      TRISB
#define TRIS_LCD_CTL      TRISD

#define RS    RD0
#define RW    RD1
#define E     RD2

//开发板端口定义
//#define PORT_LCD_DAT      PORTD
//#define PORT_LCD_CTL      PORTB
//#define TRIS_LCD_DAT      TRISD
//#define TRIS_LCD_CTL      TRISB
//
//#define RS    RB5
//#define RW    RB4
//#define E     RB3

void LCD_Initialize();
void LCD_BUSY_WAIT();
void Write_LCD_Command(INT8U data);
void Write_LCD_Data(INT8U data);
void LCD_ShowString(INT8U r,INT8U c,char *str);
void LCD_ScrolShow(INT8U r,INT8U c,char *str);
void CopyString(char *ds,char *ss,INT8U c);

main.c 

/* 
 * 文件:   main.c
 * 编写:   金伟
 * 用途:   LCD1602测试程序
 * 时间:   2019年7月16日, 下午10:56
 */

// PIC16LF877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <pic.h>
#include "LCD1602.h"

//显示的字符串
const char demo[]="----LCD DEMO----";            
const char tel[]="Welcome To PIC World  TEL:18627238500";
const char tel1[]="apple inc";
const char tel2[]="HUAWEI P10";

void main()
{
    LCD_Initialize();
    LCD_ShowString(0,0,demo);
    
//    LCD_ShowString(0,0,(char*)"----LCD DEMO----");
    
    while(1)
    {
        LCD_ScrolShow(1,0,tel);
        LCD_ScrolShow(1,0,tel1);
        LCD_ScrolShow(1,0,tel2);
    }
}

 

没有更多推荐了,返回首页