Friday, June 20, 2014

Bài 2.(Học MSP430 qua ví dụ)Đồng hồ số - Trình tự lập trình,UART,LED

1.   Trình tự lập trình

Trước khi bước vào phần này thì có nghĩa là các bạn đã thi công mạch xong.Bắt đầu chúng ta sẽ xác định tuần tự các bước lập trình:
-       Tạo Project ,chọn chip lập trình,ở đây là MSP430G2553
-       Thiết lập giao tiếp UART ,xung Clock (Clock,UART)
-       Quét Led (GPIO)
-       Đọc IC thời gian thực BQ32000,hiển thị giờ ,ngày (Ngắt , I2C)
-       Quét bàn phím , đọc nhiệt độ dùng ADC (ADC)
-       Tạo menu chương trình,viết hàm chỉnh giờ,ngày (I2C)
-       Chỉnh độ tương phản led ,hẹn giờ,đồng hồ đếm ngược(Flash)
Bây giờ thì có thể bắt tay vào lập trình được rồi.


2.   Tạo Project

Các bạn làm theo hướng dẫn như trong bài,mình sẽ không hướng dẫn lại nữa:Bài 1.(MSP430_Basic)Tạo Project
Sau khi khởi tạo Project , chúng ta sẽ tạo folder “Library” trong Project vừa tạo,dùng để chứa các thư viện sẽ được sử dụng.

Kết nối giao diện debug như trong Tutorial,chú ý nối chân Tx của Mạch với Rx của KIT.

Chúng ta sẽ thống nhất khung chương trình của một file( cả file main và file thư viện đều như nhau để dễ quản lý).
////////////////////////////////////////////////////////////////////
// KHUNG TIEU DE
//******************************************************************/


/******************************************************************************\
*                                             MO TA CHUONG TRINH                  *
\******************************************************************************/

/******************************************************************************\
*                                                    DEFINE                      *
\******************************************************************************/

/******************************************************************************\
*                                              BIEN TOAN CUC               *
\******************************************************************************/

/******************************************************************************\
*                                              NGUYEN MAU HAM,MACRO        *
\******************************************************************************/

/******************************************************************************\
*                                              HAM MAIN                           *
\******************************************************************************/

/******************************************************************************\
*                                 Function (noi dung ham)                        *
\******************************************************************************/

Thực ra ngay cả mình cũng không phải lúc nào cũng nhớ để làm theo y hệt như trên,tuy nhiên các bạn nên tập trình bày theo một chuẩn nhất định,để thuận lợi cho việc viết code.

3.   Khởi tạo GPIO,thiết lập UART

Giao tiếp UART với máy tính có đặc điểm là chỉ cần 1 hoặc 2 chân mà lại có thể hiển thị được rất nhiều thông tin lên màn hình máy tính.
Các bạn có thể đọc qua bài giao tiếp UART trong Tutorial_MSP430,download thư viện UART.h để sử dụng.
Bắt đầu bằng việc gọi thư viện chip sử dụng: #include <msp430g2553.h>.Tạo hàm Initial để chứa phần khởi tạo chương trình.
Sau đó cài đặt tắt Watchdog và cài đặt xung đồng hồ nội 1Mhz.Các bạn có thể download thư viện Clock hoặc chỉnh trực tiếp trong thanh ghi.
//Set up Watchdog
WDTCTL = WDTPW | WDTHOLD;                //Ngung Watchdog
DCOCTL = CALDCO_1MHZ;                           //Xung dong ho noi 1Mhz
BCSCTL1 = CALBC1_1MHZ;

Cài đặt giá trị các thanh ghi GPIO ở ngay đầu tiên của chương trình để đảm bảo điện áp logic không vô tình ảnh hưởng đến bất cứ điều gì khác.Việc điều khiển Loa rất dễ dàng,chúng ta viết Macro bật và tắt loa để đỡ phải nhớ vị trí của pin điều khiển loa,đặt ở trong phần “nguyên mẫu hàm”.Các bạn có thể đọc lại bài GPIO để hiểu rõ hơn:Bài 2.(MSP430_Basic)GPIO.
//Khoi tao GPIO
       P1DIR=BIT1+BIT2+BIT6+BIT7;
       P1OUT|=BIT1+BIT2+BIT6+BIT7;
       P2DIR=0xFF;
       P2SEL=0x00;
       P2REN=0x00;
       P2OUT=0x80;          //Tat dau hai cham
       Do_chuong();
       _delay_cycles(100000);
       Ngat_chuong();

Tiếp theo gọi thư viện UART.h ,chúng ta sẽ sử dụng thêm hàm tạo chuỗi sprintf nên phải khai báo thêm thư viện stdio.h.Vì hai hàm UART.h và stdio.h sẽ không được sử dụng khi mạch làm việc thực tế,chúng ra đặt khai báo #ifdef USE_UART ở các vị trí sử dụng UART,khi muốn dùng UART thì chỉ cần tạo #define USE_UART là được.(Từ khóa ifdef cho phép trình dịch đọc các lệnh ở trong nó nếu trước đó đã có khai báo #define USE_UART,nếu không có khai báo #define này thì trình dịch sẽ bỏ qua các lện giữa #ifdef và #endif).Tạo một mảng char buff[30] để dùng với hàm sprintf sau này.Các bạn có thể đọc lại bài hướng dẫn về UART ở đây
#ifdef USE_UART
#include "Library/UART.h"
#include "stdio.h"
#endif
Chúng ta sẽ giao tiếp UART ở tần số 9600(Kit Launchpad chỉ hỗ trợ tần số này), trong thư viện UART có 2 thông số phải cài đặt là SMCLK_F là tần số hoạt động hiện thời của VDK và BAUDRATE chính là tần số hoạt động của UART,chỉnh SMLCK_F=1000000 và BAUDRATE = 9600.Sau đó gọi hàm UART_Init() . Hàm này sẽ cài đặt các thanh ghi phục vụ cho giao tiếp UART và cập nhật tần số hoạt động từ 2 biến SMCLK_F và BAUDRATE.
#ifdef USE_UART
       SMCLK_F=1000000;
       BAUDRATE =9600;
       UART_Init();
       UART_Write_String("Ket noi thanh cong");
       UART_Write_Char(10); //Ki tu xuong dong
#endif

Set chế độ LPM0 ở cuối chương trình để chương trình không thoát ra ngoài sau khi thực hiện hết các lệnh.Khi tạo được 1 vòng khép kín của chương trình thì có thể xóa hàm này đi.
Cuối cùng sẽ được chương trình sau:
////////////////////////////////////////////////////////////////////
// DONG HO SO DUNG MSP430
// VIET BOI : PHAM VAN THUAN      DTVT07-K55-20/6/2014
// Blog :ThuanBK55.blogspot.com
// .................................................................
// AP DUNG MSP430
//******************************************************************/

/*****************************************************************************\
*                                           MO TA CHUONG TRINH                *
\******************************************************************************/
/*
 * Chu y delay trong quet led chi duoc phep gioi han trong 300
 * Cac chuc nang can co:
 *            - Xem gio
 *            - Xem ngay
 *            - Xem nhiet do
 *            - Chinh gio,ngay
 *            - Chinh do sang tu dong,bang tay
 *            - Hen gio
 *            - Dong ho dem nguoc
 */

/*
 * Ma hoa Led
 *                  6
 *     5-o    ---------
 *            |             |
 *     4     |      3      |7
 *            ---------
 *      2     |             |
 *            |      0      |1
 *            ---------
 */
/*****************************************************************************\
*                                                    DEFINE                   *
\******************************************************************************/
#define USE_UART
/*****************************************************************************\
*                                              BIEN TOAN CUC                  *
\*****************************************************************************/
//Bien dung cho UART
char buff[30];
/*****************************************************************************\
*                                              NGUYEN MAU HAM,MACRO           *
\*****************************************************************************/
#include <msp430g2553.h>
#ifdef USE_UART
#include "Library/UART.h"
#include "stdio.h"
#endif

void Initial();
/*****************************************************************************\
*                                              MAIN                           *
\*****************************************************************************/

void main(void)
{
       Initial();
       __bis_SR_register(LPM0);
}
/*****************************************************************************\
*                                 Function (noi dung ham)                     *
\*****************************************************************************/

void Initial()
{
       //Set up Watchdog
       WDTCTL = WDTPW | WDTHOLD;                //Ngung Watchdog
       DCOCTL = CALDCO_1MHZ;                           //Xung dong ho noi 1Mhz
       BCSCTL1 = CALBC1_1MHZ;

       //Khoi tao GPIO
       P1DIR=BIT1+BIT2+BIT6+BIT7;
       P1OUT|=BIT1+BIT2+BIT6+BIT7;
       P2DIR=0xFF;
       P2SEL=0x00;
       P2REN=0x00;
       P2OUT=0x80;          //Tat dau hai cham
      //Cho loa keu
       Do_chuong();
       _delay_cycles(100000);
       Ngat_chuong();
       //Khoi tao UART
#ifdef USE_UART
       SMCLK_F=1000000;
       BAUDRATE =9600;
       UART_Init();
       UART_Write_String("Ket noi thanh cong");
       UART_Write_Char(10); //Ki tu xuong dong
#endif
}
Đến đây bạn có thể dùng Terminal để kiểm tra xem kết nối UART đã hoạt động chưa.

4.   Quét LED

Datasheet của Led clock sử dụng:

Sơ đồ nối dây khối quét Led.

Nguyên lý quét led như sau.
-       Các chân 14,11,10,6 ứng với chân dương các số từ trái sang phải quyết định số nào sáng tại 1 thời điểm.Khi quét led thì chỉ 1 được sáng 1 trong 4 số .Các chân này được nối trực tiếp với chân VĐK,chân 8 điều khiển 2 dấu chấm.
-       Các chân còn lại của led(13,9,4,2,1,12,5,3) gọi là “soled” sẽ quyết định số hiển thị lên có dạng thế nào.Mức logic 0 thì led sáng,1 thì led tắt.Từ sơ đồ nối dây và datasheet của Led sẽ tính ra chuỗi giá trị ứng với số hiển thị ra từ 0 đến 9.Chú ý là chúng ra quay ngược led (để dấu chấm hiển thị cho chữ *C).
-       Ví dụ muốn hiển thị số 1 thì cần để mức logic 0 với các vị trí 1 và 7 soled[1]=0x7D .Tương tự với các số khác.Chúng ra định nghĩa thêm kí tự trống(soled[10]) , *C(11) , F(12) để hiển thị sau này.
/*
 * Ma hoa Led
 *                  6
 *     5-o    ---------
 *            |             |
 *     4     |      3      |7
 *            ---------
 *      2     |             |
 *            |      0      |1
 *            ---------
 */
//Bit co logic 0 sang  
//          0    1    2    3     4    5    6    7   8     9        -    *C    F
unsigned char soled[14]={0x28,0x7D,0x32,0x34,0x65,0xA4,0xA0,0x3D,0x20,0x24,0xFF,0xF7,0x8A,0xA3};
-       Để có thể quét led được thì chúng ta dùng IC74HC595 để tiết kiệm chân điều khiển.Vì trong mạch này dùng UART nên không dùng SPI cứng được(trùng chân) tuy nhiên có thể dùng SPI mềm ,rất may là việc lập trình SPI khá đơn giản.Có 3 chân cần điều khiển là R,SR,DATA.
-       Khai báo Define các chân điều khiển 74HC595
//Chan 74HC595
#define ENABLE_R_CLOCK()          P2OUT|=BIT1
#define DISABLE_R_CLOCK()          P2OUT&=~BIT1
#define ENABLE_SR_CLOCK()          P2OUT|=BIT2
#define DISABLE_SR_CLOCK()         P2OUT&=~BIT2
#define ENABLE_DATA_CLOCK()       P2OUT|=BIT0
#define DISABLE_DATA_CLOCK()      P2OUT&=~BIT0

-       Các bạn có thể đọc thêm datasheet để hiểu rõ hơn về IC này.Quy trình để ghi 1 byte ra như sau:
o   Cho R=0 để giữ mức logic từ lần quét led trước.
o   G(chân 13)=0 thì cho phép xuất dữ liệu từ bộ đệm 74HC595 ra,G=1 thì đầu ra cao trở.Trong mạch nối đất.
o   CLEAR (chân 10) =0 thì xóa dữ liệu trong bộ đệm.Trong mạch nối nguồn.
o   SR từ 0->1 để cho phép ghi dữ liệu từ bên ngoài vào bộ đệm.
o   Cho SR=0 ,ghi dữ liệu bit đang quét vào chân DATA,cho SR=1 để ghi vào bộ đệm.Lặp lại 8 lần để ghi hết dữ liệu của 1 byte.
o   R=1 để xuất dữ liệu từ bộ đệm ra ngoài.
-       Tạo hàm Write_74HC595_8bit(unsigned char x).
void Write_74HC595_8bit(unsigned char x)
{
       unsigned char tem=0;
       unsigned char i;
       DISABLE_R_CLOCK();
       for(i=0;i<8;i++)
       {
              DISABLE_SR_CLOCK();
              tem=(((1<<(7-i))&x)!=0);
              if (tem==0)   DISABLE_DATA_CLOCK();
              else   ENABLE_DATA_CLOCK();
              ENABLE_SR_CLOCK();
       }
       ENABLE_R_CLOCK();
}
-       Tạo Macro chọn số cần quét ra
// Chon so can quet
#define GIO10_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT6
#define GIO_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT5
#define PHUT10_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT4
#define PHUT_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT3

-       Viết thử chương trình kiểm tra xem giá trị Led có đúng không,trong hàm main
void main(void)
{
       unsigned char abc=0;
       Initial();
       GIO10_ON;
       while(1)
       {
              Write_74HC595_8bit(soled[abc]);
              if(abc<13)abc++;
              else abc=0;
              _delay_cycles(1000000);
       }
       __bis_SR_register(LPM0);
}
-       Như vậy là đã xong quét led
Hàm main
////////////////////////////////////////////////////////////////////
// DONG HO SO DUNG MSP430
// VIET BOI : PHAM VAN THUAN      DTVT07-K55-20/6/2014
// Blog :ThuanBK55.blogspot.com
// .................................................................
// AP DUNG MSP430
//******************************************************************/

/******************************************************************************\
*                                             MO TA CHUONG TRINH               *
\******************************************************************************/
/*
 * Chu y delay trong quet led chi duoc phep gioi han trong 300
 * Cac chuc nang can co:
 *            - Xem gio
 *            - Xem ngay
 *            - Xem nhiet do
 *            - Chinh gio,ngay
 *            - Chinh do sang tu dong,bang tay
 *            - Hen gio
 *            - Dong ho dem nguoc
 */

/*
 * Ma hoa Led
 *                  6
 *     5-o    ---------
 *            |             |
 *     4     |      3      |7
 *            ---------
 *      2     |             |
 *            |      0      |1
 *            ---------
 */
/******************************************************************************\
*                                                    DEFINE                     *
\******************************************************************************/
#define USE_UART
//Chan 74HC595
#define ENABLE_R_CLOCK()   P2OUT|=BIT1
#define DISABLE_R_CLOCK()    P2OUT&=~BIT1
#define ENABLE_SR_CLOCK()  P2OUT|=BIT2
#define DISABLE_SR_CLOCK() P2OUT&=~BIT2
#define ENABLE_DATA_CLOCK()       P2OUT|=BIT0
#define DISABLE_DATA_CLOCK()      P2OUT&=~BIT0
/******************************************************************************\
*                                              BIEN TOAN CUC                    *
\******************************************************************************/
//Bien dung cho UART
char buff[30];
//Bit co logic 0 sang      0    1    2   3     4    5    6    7   8     9        -    *C    F
unsigned char soled[14]={0x28,0x7D,0x32,0x34,0x65,0xA4,0xA0,0x3D,0x20,0x24,0xFF,0xF7,0x8A,0xA3};
/******************************************************************************\
*                                              NGUYEN MAU HAM,MACRO             *
\******************************************************************************/
// Dieu khien chuong
#define Do_chuong()        P1OUT |=BIT1;
#define Ngat_chuong()      P1OUT &=~BIT1;
// Chon so can quet
#define GIO10_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT6
#define GIO_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT5
#define PHUT10_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT4
#define PHUT_ON P2OUT = (P2OUT & (BIT0+BIT1+BIT2+BIT7))|BIT3

#include <msp430g2553.h>
#ifdef USE_UART
#include "Library/UART.h"
#include "stdio.h"
#endif

void Initial();
void Write_74HC595_8bit(unsigned char x);
/******************************************************************************\
*                                              HAM MAIN                        *
\******************************************************************************/

void main(void)
{
       unsigned char abc=0;
       Initial();
       GIO10_ON;
       while(1)
       {
              Write_74HC595_8bit(soled[abc]);
              if(abc<13)abc++;
              else abc=0;
              _delay_cycles(1000000);
       }
       __bis_SR_register(LPM0);
}

/******************************************************************************\
*                                               Function (noi dung ham)        *
\******************************************************************************/

void Initial()
{
       //Set up Watchdog
       WDTCTL = WDTPW | WDTHOLD;                //Ngung Watchdog
       DCOCTL = CALDCO_1MHZ;                           //Xung dong ho noi 1Mhz
       BCSCTL1 = CALBC1_1MHZ;

       //Khoi tao GPIO
       P1DIR=BIT1+BIT2+BIT6+BIT7;
       P1OUT|=BIT1+BIT2+BIT6+BIT7;
       P2DIR=0xFF;
       P2SEL=0x00;
       P2REN=0x00;
       P2OUT=0x80;          //Tat dau hai cham
       //Cho loa keu
       Do_chuong();
       _delay_cycles(100000);
       Ngat_chuong();
       //Khoi tao UART
#ifdef USE_UART
       SMCLK_F=1000000;
       BAUDRATE =9600;
       UART_Init();
       UART_Write_String("Ket noi thanh cong");
       UART_Write_Char(10); //Ki tu xuong dong
#endif
}


void Write_74HC595_8bit(unsigned char x)
{
       unsigned char tem=0;
       unsigned char i;
       DISABLE_R_CLOCK();
       for(i=0;i<8;i++)
       {
              DISABLE_SR_CLOCK();
              tem=(((1<<(7-i))&x)!=0);
              if (tem==0)   DISABLE_DATA_CLOCK();
              else   ENABLE_DATA_CLOCK();
              ENABLE_SR_CLOCK();
       }
       ENABLE_R_CLOCK();
}

No comments:

Post a Comment

END COMMENT FACEBOOK-->