MSP430F169(三) ---- 使用UART實現PC與單片機的數據收發並在1602 液晶顯示

本代碼需要注意的細節

  1. 每次字符串的發送時間至少間隔三秒,發送的字符的數量最好在32個以內,防止數據接收不全。
  2. 本代碼波特率的設置爲1200.如果波特率設置過高,會出現數據接收不全的問題。我試過9600的波特率,會出現問題。讀者可以自行修改代碼,實現更高的傳輸速率。
  3. 有關的細節會在代碼中說明

代碼實現

主函數

#include <msp430f169.h>
#include "Config.h"
#include "LCD.h"
#include "Init.h"
#include "UART.h"
//#include "stdlib.h"    本來想用全局指針來存儲接收的數據
//                       結果發現自己用不來........
//#include "string.h"
//unsigned char a[60];

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;	        //停止看門狗
    Clock_Init();                       //系統時鐘設置
    LCD_Port_init();                    //LCD IO初始化
    delay_ms(100);                      //延時100ms,
    LCD_init();                         //液晶參數初始化設置
    LCD_clear();                        //清屏

    UART_Init();                        //串口設置初始化
    _EINT();                            //開中斷
    Print_Str("DM430-L Board UART Test...\n");//發送字符串測試,使用串口助手顯示
    while(1)
    {
      LPM0;                             //採用低功耗模式接收中斷
    }
}

UART.C配置

/*
 * UART.c
 *
 *  Created on: 2020年4月20日
 *      Author: qq_rowosr
 */

#include "UART.h"
#include "stdlib.h"
//#include "string.h"
//#include "LCD.h"
//extern unsigned char a[60];

//串口初始化
void UART_Init()
{
  U0CTL|=SWRST + CHAR;                //復位SWRST,8位數據模式
  U0TCTL|=SSEL1;                      //SMCLK爲串口時鐘
  U0BR1=0X1A;                       //BRCLK=8MHZ,Baud=BRCLK/N
  U0BR0=0X0A;                       //N=UBR+(UxMCTL)/8
  U0MCTL=0x00;                        //微調寄存器爲0,波特率1200bps
  ME1|=UTXE0;                         //UART0發送使能
  ME1|=URXE0;                         //UART0接收使能
  U0CTL&=~SWRST;
  IE1|=URXIE0;                        //接收中斷使能位

  P3SEL|= BIT4 + BIT5;                //設置IO口爲第二功能模式,啓用UART功能
  P3DIR|= BIT4;                       //設置TXD0口方向爲輸出
}

void Send_Byte(uchar data)
{
  while(!(IFG1&UTXIFG0));          //發送寄存器空的時候發送數據
    U0TXBUF=data;
}


//*************************************************************************
//              串口0發送字符串函數
//*************************************************************************
void Print_Str(uchar *s)
{
    while(*s != '\0')
    {
        Send_Byte(*s++);
    }
}
//**************************************
//              中斷函數
//**************************************
#pragma vector=USART0RX_VECTOR
__interrupt void UART0_RX_ISR(void)
{
    LPM0_EXIT;                      //退出低功耗
    uchar data = 0;
    data = U0RXBUF;                 //接收到的數據存起來
    Send_Byte (data);               //將接收到的數據再發送出去
    Display_Character_String(data); //在1602顯示接收的字符
}

UART.h

/*
 * UART.h
 *
 *  Created on: 2020年4月20日
 *      Author: QQ_rowosr
 */
#ifndef UART_H_
#define UART_H_
#include <msp430f169.h>
#include "Config.h"

void Print_Str(uchar *s);
void Send_Byte(uchar data);
void UART_Init();

#endif /* UART_H_ */

LCD.h

/*
 * 1602.h
 *
 *  Created on: 2020年4月20日
 *      Author: QQ_rowosr
 */
#ifndef LCD_H_
#define LCD_H_
#include <msp430f169.h>
#include "Config.h"

void LCD_Port_init();
void LCD_write_com(unsigned char com);
void LCD_write_data(unsigned char data);
void LCD_clear(void);
void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s);
void LCD_write_char(unsigned char x,unsigned char y,unsigned char data);
void LCD_init(void);
void Display_Character_String(unsigned char data);


#endif /* 1602_H_ */

LCD.c

/*
 * 1602.c
 *
 *  Created on: 2020年4月20日
 *      Author: QQ_rowosr
 */
#include "LCD.h"

//*************************************************************************
//          初始化IO口子程序
//*************************************************************************
void LCD_Port_init()
{

    P4SEL = 0x00;
    P4DIR = 0xFF;                   //數據口輸出模式
    P5SEL = 0x00;
    P5DIR |= BIT5 + BIT6 + BIT7;     //控制口設置爲輸出模式
}


//***********************************************************************
//  顯示屏命令寫入函數
//***********************************************************************
void LCD_write_com(unsigned char com)
{
    RS_CLR;
    RW_CLR;
    EN_SET;
    DataPort = com;                 //命令寫入端口
    delay_us(100);
    EN_CLR;
}

//***********************************************************************
//  顯示屏數據寫入函數
//***********************************************************************
void LCD_write_data(unsigned char data)
{
    RS_SET;
    RW_CLR;
    EN_SET;
    DataPort = data;                //數據寫入端口
    delay_us(100);
    EN_CLR;
}

//***********************************************************************
//  顯示屏清空顯示
//***********************************************************************
void LCD_clear(void)
{
    LCD_write_com(0x01);            //清屏幕顯示
    delay_ms(5);
}

//***********************************************************************
//  顯示屏字符串寫入函數
//***********************************************************************
void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s)
{

    if (y == 0)
    {
        LCD_write_com(0x80 + x);        //第一行顯示
    }
    else
    {
        LCD_write_com(0xC0 + x);        //第二行顯示
    }

    while (*s)
    {
        LCD_write_data( *s);
        s ++;
    }
}

//***********************************************************************
//  顯示屏單字符寫入函數
//***********************************************************************
void LCD_write_char(unsigned char x,unsigned char y,unsigned char data)
{

    if (y == 0)
    {
        LCD_write_com(0x80 + x);        //第一行顯示
    }
    else
    {
        LCD_write_com(0xC0 + x);        //第二行顯示
    }

    LCD_write_data( data);
}

//***********************************************************************
//  顯示屏初始化函數
//***********************************************************************
void LCD_init(void)
{
    LCD_write_com(0x38);        //顯示模式設置
    delay_ms(5);
    LCD_write_com(0x08);        //顯示關閉
    delay_ms(5);
    LCD_write_com(0x01);        //顯示清屏
    delay_ms(5);
    LCD_write_com(0x06);        //顯示光標移動設置
    delay_ms(5);
    LCD_write_com(0x0C);        //顯示開及光標設置
    delay_ms(5);
}
//************************************
//          字符串顯示函數
//***********************************
void Display_Character_String(unsigned char data)
{

    static int i = 0;
    static int y = 0;
    if (i % 2 == 0)     //第一行顯示
    {
    LCD_write_com (0x80 + y);       
    LCD_write_data (data);
    y++;
    if (y == 16){ i++;y = 0;}
    }
    else            //第二行顯示
    {

            LCD_write_com (0xc0 + y);
            LCD_write_data (data);
            y++;

        if (y == 16)
        {
            i++ ;
            y = 0;
            delay_ms(1000);     //讀者可以自行設置延時時間,但是兩次發送字符串的間隔時間,大於你設置的延時時間
            LCD_clear();        //接收到32個字符,清屏
        }
    }
}

Config.h

/*
 * Config.h
 *
 *  Created on: 2020年4月20日
 *      Author: QQ_rowosr
 */
#ifndef CONFIG_H_
#define CONFIG_H_

#define CPU_F ((double)8000000)   //外部高頻晶振8MHZ
//#define CPU_F ((double)32768)   //外部低頻晶振32.768KHZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

//自定義數據結構,方便使用
#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long

//8個LED燈,連接在P6口,可通過斷開電源停止使用,ADC使用時斷開電源
#define LED8DIR         P6DIR
#define LED8            P6OUT                             //P6口接LED燈,8個

//4個獨立按鍵連接在P10~P13
#define KeyPort         P1IN                              //獨立鍵盤接在P10~P13

//串口波特率計算,當BRCLK=CPU_F時用下面的公式可以計算,否則要根據設置加入分頻係數
#define baud           9600                                //設置波特率的大小
#define baud_setting   (uint)((ulong)CPU_F/((ulong)baud))  //波特率計算公式
#define baud_h         (uchar)(baud_setting>>8)            //提取高位
#define baud_l         (uchar)(baud_setting)               //低位

//RS485控制管腳,CTR用於控制RS485處於收或者髮狀態
#define RS485_CTR1      P5OUT |= BIT2;          //控制線置高,RS485發送狀態
#define RS485_CTR0      P5OUT &= ~BIT2;         //控制線置低,RS485接收狀態

//2.8寸TFT彩屏顯示控制相關硬件配置
#define RS_CLR          P5OUT &= ~BIT5           //RS置低
#define RS_SET          P5OUT |=  BIT5           //RS置高

#define RW_CLR          P5OUT &= ~BIT6           //RW置低
#define RW_SET          P5OUT |=  BIT6           //RW置高

#define RD_CLR          P5OUT &= ~BIT7           //E置低
#define RD_SET          P5OUT |=  BIT7           //E置高

#define CS_CLR          P5OUT &= ~BIT0            //CS置低
#define CS_SET          P5OUT |=  BIT0            //CS置高

#define RST_CLR         P5OUT &= ~BIT3            //RST置低
#define RST_SET         P5OUT |=  BIT3            //RST置高

#define LE_CLR          P5OUT &= ~BIT1            //LE置低
#define LE_SET          P5OUT |=  BIT1            //LE置高

//2.8寸TFT彩屏觸摸屏控制相關硬件配置
#define PEN_CLR         P2OUT &= ~BIT0           //PEN置低,觸碰觸摸屏時,Penirq引腳由未觸摸時的高電平變爲低電平
#define PEN_SET         P2OUT |=  BIT0           //PEN置高
#define PEN             (P2IN & 0x01)            //P2.0輸入的值

#define TPDO_CLR    P2OUT &= ~BIT1           //TPDO置低
#define TPDO_SET    P2OUT |=  BIT1           //TPDO置高
#define TPDOUT          ((P2IN>>1)&0x01)         //P2.1輸入的值

#define BUSY_CLR    P2OUT &= ~BIT3           //BUSY置低
#define BUSY_SET    P2OUT |=  BIT3           //BUSY置高

#define TPDI_CLR    P2OUT &= ~BIT4            //TPDI置低
#define TPDI_SET    P2OUT |=  BIT4            //TPDI置高

#define TPCS_CLR    P2OUT &= ~BIT5            //TPCS置低
#define TPCS_SET    P2OUT |=  BIT5            //TPCS置高

#define TPCLK_CLR   P2OUT &= ~BIT6            //TPCLK置低
#define TPCLK_SET   P2OUT |=  BIT6            //TPCLK置高

//彩屏/12864液晶/1602液晶的數據口,三液晶共用
#define DataDIR         P4DIR                     //數據口方向
#define DataPort        P4OUT                     //P4口爲數據口

//12864/1602液晶控制管腳
#define RS_CLR          P5OUT &= ~BIT5           //RS置低
#define RS_SET          P5OUT |=  BIT5           //RS置高

#define RW_CLR          P5OUT &= ~BIT6           //RW置低
#define RW_SET          P5OUT |=  BIT6           //RW置高

#define EN_CLR          P5OUT &= ~BIT7           //E置低
#define EN_SET          P5OUT |=  BIT7           //E置高

#define PSB_CLR         P5OUT &= ~BIT0            //PSB置低,串口方式
#define PSB_SET         P5OUT |=  BIT0            //PSB置高,並口方式

#define RST_CLR         P5OUT &= ~BIT1            //RST置低
#define RST_SET         P5OUT |= BIT1             //RST置高

//12864應用指令集
#define CLEAR_SCREEN    0x01                  //清屏指令:清屏且AC值爲00H
#define AC_INIT     0x02                  //將AC設置爲00H。且遊標移到原點位置
#define CURSE_ADD   0x06                  //設定遊標移到方向及圖像整體移動方向(默認遊標右移,圖像整體不動)
#define FUN_MODE    0x30                  //工作模式:8位基本指令集
#define DISPLAY_ON  0x0c                  //顯示開,顯示遊標,且遊標位置反白
#define DISPLAY_OFF 0x08                  //顯示關
#define CURSE_DIR   0x14                  //遊標向右移動:AC=AC+1
#define SET_CG_AC   0x40                  //設置AC,範圍爲:00H~3FH
#define SET_DD_AC   0x80                      //設置DDRAM AC
#define FUN_MODEK   0x36                  //工作模式:8位擴展指令集

//顏色代碼,TFT顯示用
#define White          0xFFFF                                                               //顯示顏色代碼
#define Black          0x0000
#define Blue           0x001F
#define Blue2          0x051F
#define Red            0xF800
#define Magenta        0xF81F
#define Green          0x07E0
#define Cyan           0x7FFF
#define Yellow         0xFFE0

//NRF2401模塊控制線
#define  RF24L01_CE_0        P1OUT &=~BIT5         //CE在P15
#define  RF24L01_CE_1        P1OUT |= BIT5

#define  RF24L01_CSN_0       P2OUT &=~BIT7         //CS在P27
#define  RF24L01_CSN_1       P2OUT |= BIT7

#define  RF24L01_SCK_0       P3OUT &=~BIT3         //SCK在P33
#define  RF24L01_SCK_1       P3OUT |= BIT3

#define  RF24L01_MISO_0      P3OUT &=~BIT2         //MISO在P32
#define  RF24L01_MISO_1      P3OUT |= BIT2

#define  RF24L01_MOSI_0      P3OUT &=~BIT1         //MOSI在P31
#define  RF24L01_MOSI_1      P3OUT |= BIT1

#define  RF24L01_IRQ_0       P1OUT &=~BIT4         //IRQ在P14
#define  RF24L01_IRQ_1       P1OUT |= BIT4

//DS18B20控制腳,單腳控制
#define DQ_IN           P1DIR &= ~BIT7        //設置輸入,DS18B20接單片機P53口
#define DQ_OUT          P1DIR |= BIT7         //設置輸出
#define DQ_CLR          P1OUT &= ~BIT7            //置低電平
#define DQ_SET          P1OUT |= BIT7             //置高電平
#define DQ_R            P1IN & BIT7       //讀電平

//紅外接收頭H1838控制腳,單腳控制
#define RED_IN          P1DIR &= ~BIT6            //設置輸入,紅外接收頭接單片機PE3口
#define RED_OUT         P1DIR |=  BIT6            //設置輸出
#define RED_L           P1OUT &= ~BIT6            //置低電平
#define RED_H           P1OUT |= BIT6             //置高電平
#define RED_R           (P1IN & BIT6)             //讀電平

#endif /* CONFIG_H_ */

Init.h

/*
 * Init.h
 *
 *  Created on: 2020年4月20日
 *      Author: QQ_rowosr
 */

#ifndef INIT_H_
#define INIT_H_
#include <msp430f169.h>
#include "Config.h"

void Clock_Init_Inc()
{
  uchar i;

 // DCOCTL = DCO0 + DCO1 + DCO2;              // Max DCO
 // BCSCTL1 = RSEL0 + RSEL1 + RSEL2;          // XT2on, max RSEL

  DCOCTL = 0x60 + 0x00;                       //DCO約3MHZ,3030KHZ
  BCSCTL1 = DIVA_0 + 0x07;
  BCSCTL2 = SELM_2 + DIVM_0 + SELS + DIVS_0;
}

//***********************************************************************
//                   系統時鐘初始化,外部8M晶振
//***********************************************************************
void Clock_Init()
{
  uchar i;
  BCSCTL1&=~XT2OFF;                 //打開XT2振盪器
  BCSCTL2|=SELM1+SELS;              //MCLK爲8MHZ,SMCLK爲8MHZ
  do{
    IFG1&=~OFIFG;                   //清楚振盪器錯誤標誌
    for(i=0;i<100;i++)
       _NOP();
  }
  while((IFG1&OFIFG)!=0);           //如果標誌位1,則繼續循環等待
  IFG1&=~OFIFG;
}



#endif /* INIT_H_ */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章