Training

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 101

Training

Tài liệu
Hướng dẫn lập trình
Vi điều khiển PIC16LF15376

www.rpc.vn
Training

Mục lục

I. Giới thiệu board UMB1P.0-15376 V1.0 và Unibus .............1


II. Lập trình xuất nhận I/O .......................................................4
1. GPIO ....................................................................................4
2. Button .................................................................................. 9
3. Timer ................................................................................. 12
4. Counter and mode LCD 4 - bit ......................................... 15
III. Điều khiển động cơ DC ..................................................... 21
IV. Truyền thông nối tiếp ........................................................27
1. I2C sensor RPR-0521RS .................................................. 27
2. ADC Sensor ...................................................................... 36
3. EEPROM 25AA1024 ........................................................40
4. I2C_RTCC_MCP7941x ....................................................62
V. Truyền thông CAN ..............................................................74
Phụ lục .......................................................................................95
Tài liệu tham khảo ................................................................... 97

www.rpc.vn
Training

Danh mục hình ảnh


Hình 1. 1 Board UMB1P.0-15376 .......................................................................... 1
Hình 1. 2 Sơ đồ nguyên lý .......................................................................................3
Hình 1. 3 Unibus ..................................................................................................... 3
Hình 1. 4 PIC16LF15376 ........................................................................................3
Hình 2. 1 Nguyên lý của project GPIO ................................................................... 4
Hình 2. 2 Khởi động MCC ......................................................................................4
Hình 2. 3 Những module sử dụng trong dự án GPIO ............................................. 5
Hình 2. 4 Cấu hình Pin Manager Gird View GPIO ................................................ 5
Hình 2. 5 Cấu hình Pin Module GPIO .................................................................... 5
Hình 2. 6 Cấu hình System Module GPIO ..............................................................6
Hình 2. 7 Giao diện Projects GPIO .........................................................................7
Hình 2. 8 Giao diện của file main.c ........................................................................ 7
Hình 2. 9 Nguyên lý của Button ..............................................................................9
Hình 2. 10 Các module sử dụng trong dự án Button ...............................................9
Hình 2. 11 Cấu hình Pin Manager Gird View Button ...........................................10
Hình 2. 12 Cấu hình Interrupt Module Button ......................................................10
Hình 2. 13 Cấu hình Pin Module Button ...............................................................10
Hình 2. 14 Nguyên lý của project Timer ...............................................................12
Hình 2. 15 Các module sử dụng trong dự án Timer ..............................................12
Hình 2. 16 Cấu hình Pin Manager Gird View của Timer ..................................... 13
Hình 2. 17 Cấu hình Interrupt Module của Timer ................................................ 13
Hình 2. 18 Cấu hình Timer0 Module của Timer ...................................................13
Hình 2. 19 Sơ đồ nguyên lý sử dụng trong dự án Counter and LCD ....................15
Hình 2. 20 Các module sử dụng trong dự án Counter and LCD ...........................16
Hình 2. 21 Cấu hình Pin Manager Gird View của Counter and LCD .................. 16
Hình 2. 22 Cấu hình Timer1 Module của Counter and LCD ................................17
Hình 3. 1 Nguyên lý của module L298N .............................................................. 21
Hình 3. 2 Kích thước board và chức năng pin của module L298N ...................... 22
Hình 3. 3 Nguyên lý của Unibus ...........................................................................22
Hình 3. 4 Các module sử dụng trong dự án điều khiển động cơ ...........................23
Hình 3. 5 Cấu hình Pin Manager Gird View của dự án điều khiển động cơ .........23
Hình 3. 6 Cấu hình Interrupt Module của dự án điều khiển động cơ ....................23
Hình 3. 7 Cấu hình Pin Module của dự án điều khiển động cơ ............................ 24
Hình 3. 8 Cấu hình Interrupt module của dự án điều khiển động cơ .................... 24
Hình 3. 9 Cấu hình module PWM4 của dự án điều khiển động cơ .......................24
Hình 3. 10 Cấu hình Module Timer2 của dự án điều khiển động cơ ....................25
Hình 4. 1 Phác thảo package của RPR-0521RS ....................................................28
Hình 4. 2 Sơ đồ khối của RPR-0521RS ................................................................ 28
Hình 4. 3 Hình ảnh module Light & Proximity .................................................... 29
Hình 4. 4 Các module sử dụng trong dự án I2C sensor RPR-0521RS ................. 29
Hình 4. 5 Cấu hình Pin Manager của dự án I2C sensor RPR-0521RS ................. 30
Hình 4. 6 Cấu hình Pin Module của dự án I2C sensor RPR-0521RS ................... 30
Hình 4. 7 Cấu hình module EUSART1 của dự án I2C sensor RPR-0521RS ....... 30
Hình 4. 8 Cấu hình Module MSSP1 của dự án I2C sensor RPR-0521RS ............ 31
Hình 4. 9 Nguyên lý của dự án ADC sensor .........................................................36
Hình 4. 10 Phototrasistor(Q5) trên board ..............................................................36
Hình 4. 11 Các module cần dùng cho dự án ADC Sensor .................................... 37

www.rpc.vn
Training

Hình 4. 12 Cấu hình Pin Manager của dự án ADC Sensor ...................................37


Hình 4. 13 Cấu hình Pin Module của dự án ADC Sensor .....................................37
Hình 4. 14 Cấu hình ADC của dự án ADC Sensor ............................................... 38
Hình 4. 15 Cấu hình module EUSART của dự án ADC Sensor ...........................38
Hình 4. 16 Package và chức năng pin của EEPROM 25AA1024 .........................40
Hình 4. 17 Sơ đồ khối của EEPROM 25AA1024 .................................................40
Hình 4. 18 Hình ảnh của module EEPROM 25AA1024 ...................................... 41
Hình 4. 19 Các module sử dụng trong dự án EEPROM 25AA1024 .................... 41
Hình 4. 20 Cấu hình Pin Manager của dự án EEPROM 25AA1024 .................... 42
Hình 4. 21 Cấu hình Pin Module của dự án EEPROM 25AA1024 ...................... 42
Hình 4. 22 Cấu hình Interrupt Module của dự án EEPROM 25AA1024 ............. 42
Hình 4. 23 Cấu hình module EUSART1 của dự án EEPROM 25AA1024 .......... 43
Hình 4. 24 Cấu hình module MSSP1 của dự án EEPROM 25AA1024 ................43
Hình 4. 25 Cấu hình các bit hướng dẫn của EEPROM 25AA1024 ...................... 44
Hình 4. 26 Sơ đồ nguyên lý và chức năng Pin của Module MCP79410 ...............63
Hình 4. 27 Sơ đồ khối của MCP79410 ................................................................. 64
Hình 4. 28 Hình ảnh module RTC MCP79410 .....................................................64
Hình 4. 29 Các Module sử dụng trong dự án RTC MCP79410 ............................65
Hình 4. 30 Cấu hình Pin Manager của dự án RTC MCP79410 ............................ 65
Hình 4. 31 Cấu hình Pin Module của dự án RTC MCP79410 ..............................66
Hình 4. 32 Cấu hình Interrupt Module của dự án RTC MCP79410 ..................... 66
Hình 4. 33 Cấu hình Module Timer2 của dự án RTC MCP79410 ....................... 67
Hình 4. 34 Cấu hình Module MSSP1 của dự án RTC MCP79410 .......................67
Hình 4. 35 Cấu hình module EUSART1 của dự án RTC MCP79410 .................. 68
Hình 5. 1 Module giao tiếp CAN MCP2515 .........................................................75
Hình 5. 2 Sơ đồ nguyên lý .....................................................................................75
Hình 5. 3 Sơ đồ giao tiếp phần cứng .....................................................................76
Hình 5. 4 Kết nối module CAN với board MCU .................................................. 76
Hình 5. 5 Kết nối mạng 2 node CAN ....................................................................77
Hình 5. 6 Sơ đồ IC giao tiếp CAN MCP2515 .......................................................78
Hình 5. 7 Nguyên lý mặt nạ nhận ......................................................................... 79
Hình 5. 8 Bảng các lệnh giao tiếp SPI .................................................................. 81
Hình 5. 9 Các module sử dụng trong dự án giao thức CAN ................................. 81
Hình 5. 10 Cấu hình Pin Manager của dự án Giao thức CAN ..............................82
Hình 5. 11 Cấu hình Pin Module của dự án Giao thức CAN ................................82
Hình 5. 12 Cấu hình Interrupt Module của dự án Giao thức CAN ....................... 83
Hình 5. 13 Cấu hình Module MSSP1 của dự án Giao thức CAN .........................83
Hình 5. 14 Cấu hình module EUSART1 của dự án Giao thức CAN ....................84
Hình 5. 15 Khung truyền dữ liệu CAN ................................................................. 90

www.rpc.vn
Training Page 1

I. Giới thiệu board UMB1P.0-15376 V1.0 và Unibus

Board UMB1P.0-15375 V1.0 sử dụng vi điều khiển 8-bit PIC16LF15376

Hình 1. 1 Board UMB1P.0-15376

www.rpc.vn
Training Page 2

 Sơ đồ nguyên lý của board

www.rpc.vn
Training Page 3

Hình 1. 2 Sơ đồ nguyên lý

 UNI Bus

Hình 1. 3 Unibus

 Vi điều khiển PIC16LF15376

Hình 1. 4 PIC16LF15376

www.rpc.vn
Training Page 4

II. Lập trình xuất nhận I/O

1. GPIO

Dự án đầu tiền sử dụng nút nhấn BT1 là Input và đèn LED1 là Output

Nhấn và giữ nút BT1 làm LED1 sáng, khi nhả tay ra thì LED1 tắt

 Yêu cầu phần cứng


Board UMB1P.0-15376 V 1.0
 Yêu cầu phầm mềm
MPLAB X IDE
 Sơ đồ nguyên lý

Hình 2. 1 Nguyên lý của project GPIO

 Hướng dẫn lập trình

Mở MCC trong menu Tool->Embedded của MPLAB X IDE.


Tạo 1 dự án MPLAB X cho vi điều khiển PIC16LF15376

Hình 2. 2 Khởi động MCC

www.rpc.vn Page 4
Training Page 5

Chọn thiết bị cho dự án của bạn.Trong dự án này,những thiết bị ngoại vi cần


được lựa chọn :

Hình 2. 3 Những module sử dụng trong dự án GPIO

Mở Pin Manager: Gird View. Chọn ổ khóa RA5 ở hàng input của Pin Module
để đặt pin RA5 là input tương tự chọn ổ khóa RE0 ổ hàng output để đặt pin
RE0 là output

Hình 2. 4 Cấu hình Pin Manager Gird View GPIO

Đóng cửa sổ Pin Manager: Grid View. Sau đó, bấm chuột vào Pin Module ở
trong Project Resources area
 Phần trung tâm sẽ hiển thị RE0 và RA5 được liệt kê trên biểu đồ I / O.
 RE5 sẽ là đầu vào sẽ đọc công tắc.
 RA5 sẽ là một đầu ra và điều khiển đèn LED. Nhấp vào hộp Output để tạo
đầu ra ghim và tích vào hộp Analog để tạo đầu ra tương tự.
 Thay đổi tên của các chân thành LED1 cho RA5 và SW1 cho RE0.

Hình 2. 5 Cấu hình Pin Module GPIO

www.rpc.vn Page 5
Training Page 6

Trong phần này, cài đặt bộ dao động và cài đặt cấu hình được chọn.
 Bộ tạo dao động
 Chọn HFINTOSC từ menu thả xuống Oscillator Select.
 Chọn lựa chọn 8MHz từ menu thả xuống HF Internal Clock.
 Chọn giá trị Clock Driver là 4.
 Điều này sẽ kích hoạt bộ dao động nội bộ 2 MHz bên trong hoạt động
như là xung đồng hồ hệ thống.

Hình 2. 6 Cấu hình System Module GPIO

Ngoài ra, hãy đảm bảo rằng chế độ Low-voltage Programming Enable được
chọn ở cuối màn hình Module System.
Note : Cấu hình của System Module này được sử dụng ở tất cả dự án của
nội dung Training

Nhấp vào nút Generate để MCC tạo thư viện phần mềm cho dự án này.

www.rpc.vn Page 6
Training Page 7

Dự án bây giờ sẽ có cả Header Files và Source Files được tạo. Nó cũng phải có
một tệp main.c được tạo

Hình 2. 7 Giao diện Projects GPIO

Nhấp đúp vào tệp main.c để mở tệp đó trong cửa sổ trình chỉnh sửa:

Hình 2. 8 Giao diện của file main.c

www.rpc.vn Page 7
Training Page 8

Thêm mã code sau vào cuối tệp main.c :


void main(void)
{
// initialize the device
SYSTEM_Initialize();
while (1)
{
CLRWDT();
if(SW1_GetValue() ==0)
{
LED1_SetHigh();
}
else
{
LED1_SetLow();
}
}
}

Switch_GetValue (), LED_SetHigh () và LED_SetLow () là #define’s và


macros được tạo bởi MCC. Định nghĩa của chúng nằm trong tệp
pin_manager.h.

www.rpc.vn Page 8
Training Page 9

2. Button

Dự án sử dụng 2 nút nhấn BT1, BT2 và 2 led LED1, LED2


Dự án sử dụng 2 cách giữ lại trạng thái đầu vào của BT1, BT2 sau khi
nhấn và thả ra không làm mất trạng thái của LED
BT1 sử dụng Interrput-on-change
BT2 sử dụng hàm button()

 Yêu cầu phần cứng


Board UMB1P.0-15376 V 1.0
 Yêu cầu phầm mềm
MPLAB X IDE
 Sơ đồ nguyên lý

Hình 2. 9 Nguyên lý của Button

 Hướng dẫn lập trình

Các Module sử dụng

Hình 2. 10 Các module sử dụng trong dự án Button

www.rpc.vn Page 9
Training Page 10

Cấu hình Pin Manager Gird View

Hình 2. 11 Cấu hình Pin Manager Gird View Button

Cấu hình Interrupt Module

Hình 2. 12 Cấu hình Interrupt Module Button

Cấu hình Pin Module

Hình 2. 13 Cấu hình Pin Module Button

www.rpc.vn Page 10
Training Page 11

Main.c

#include "mcc_generated_files/mcc.h"

void led_toggle (void) //hàm toggle LED1


{
LED1_Toggle();
}

uint8_t button(uint8_t numbutt) //hàm button lưu trạng thái nút nhấn
{
static uint8_t press=0;
if(numbutt == 0 && press == 0)
{
press = 1;
return 1;
}
else if(numbutt == 1)
{
press = 0;
}
return 0;
}

void main(void)
{
// initialize the device
SYSTEM_Initialize();
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();
IOCAF5_SetInterruptHandler(led_toggle); // RA5 Interrupt-on-change
while (1)
{
CLRWDT();
// Add your application code
if(button(SW2_GetValue())) // Đọc trạng thái BT2
{
LED2_Toggle();
}
}
}

www.rpc.vn Page 11
Training Page 12

3. Timer

Dự án sử dụng LED1
LED1 sẽ bật/tắt liên tục trong 1s

 Yêu cầu phần cứng


Board UMB1P.0-15376 V 1.0
 Yêu cầu phầm mềm
MPLAB X IDE
 Sơ đồ nguyên lý

Hình 2. 14 Nguyên lý của project Timer

 Hướng dẫn lập trình


Các Module sử dụng trong dự án

Hình 2. 15 Các module sử dụng trong dự án Timer

www.rpc.vn Page 12
Training Page 13

Cấu hình Pin

Hình 2. 16 Cấu hình Pin Manager Gird View của Timer

Cấu hình Interrupt Module

Hình 2. 17 Cấu hình Interrupt Module của Timer

Cấu hình Timer0 Module

Hình 2. 18 Cấu hình Timer0 Module của Timer

www.rpc.vn Page 13
Training Page 14

Main.c

#include "mcc_generated_files/mcc.h"

uint8_t volatile count=0;

void Led_1s (void) //Hàm delay led 1s


{
count++;
if(count >= 25)
{
LED3_Toggle();
count = 0;
}
}

void main(void)
{
// initialize the device
SYSTEM_Initialize();

// Enable the Global Interrupts


INTERRUPT_GlobalInterruptEnable();

// Enable the Peripheral Interrupts


INTERRUPT_PeripheralInterruptEnable();
TMR0_SetInterruptHandler(Led_1s);
while (1)
{
CLRWDT();
// Add your application code
}
}

www.rpc.vn Page 14
Training Page 15

4. Counter and mode LCD 4 - bit

Dự án sử dụng Timer1 làm bộ đếm Counter, LCD 16x2 để hiển thị bộ đếm
số thập phân và nút nhấn BT1 làm T1CKI cho bộ đếm
Khi nhấn BT1 bộ đếm sẽ đếm lên 1 lần
Nhấn BT3 bộ đếm sẽ được làm mới

 Yêu cầu phần cứng


Board UMB1P.0-15376 V 1.0
LCD 16x2
 Yêu cầu phầm mềm
MPLAB X IDE

 Sơ đồ nguyên lý

Hình 2. 19 Sơ đồ nguyên lý sử dụng trong dự án Counter and LCD

www.rpc.vn Page 15
Training Page 16

 Hướng dẫn lập trình

Các module sử dụng trong dự án

Hình 2. 20 Các module sử dụng trong dự án Counter and LCD

Cấu hình Pin

Hình 2. 21 Cấu hình Pin Manager Gird View của Counter and LCD

www.rpc.vn Page 16
Training Page 17

Cấu hình Timer1 Module

Hình 2. 22 Cấu hình Timer1 Module của Counter and LCD

Cấu hình Pin Module

Hình 2. 23 Cấu hình Pin Module của Counter and LCD

www.rpc.vn Page 17
Training Page 18

Thêm file thư viện “LCD.h” và “LCD.c” vào project

LCD.h

#include <xc.h>
#include "pin_manager.h"
#define LCD_RS LCD_RS_LAT
#define LCD_E LCD_E_LAT
#define LCD_DB4 LCD_DB4_LAT
#define LCD_DB5 LCD_DB5_LAT
#define LCD_DB6 LCD_DB6_LAT
#define LCD_DB7 LCD_DB7_LAT

void LCD_Port (char bits);


void LCD_Command (char cmnd);
void LCD_Char (char char_data);
void LCD_Init (void);
void LCD_Clear(void);
void LCD_gotoxy (char x, char y);
void LCD_String (char *str);
void LCD_String_xy (char row, char pos, char *str);

LCD.c
#include "LCD4bit.h"
#include "device_config.h"

void LCD_Port (char bits)


{
if(bits&1)
LCD_DB4_SetHigh();
else
LCD_DB4_SetLow();
bits>>=1;
if(bits&1)
LCD_DB5_SetHigh();
else
LCD_DB5_SetLow();
bits>>=1;
if(bits&1)
LCD_DB6_SetHigh();
else
LCD_DB6_SetLow();
bits>>=1;
if(bits&1)
LCD_DB7_SetHigh();
else
LCD_DB7_SetLow();
}

www.rpc.vn Page 18
Training Page 19

void LCD_Command (char cmnd) /* LCD16x2 command funtion */


{
LCD_Port(cmnd>>4);/* Send upper nibble */
LCD_RS =0; /* Command reg. */
LCD_E =1;
__delay_us(1000);
LCD_E=0;
__delay_us(2000);

LCD_Port(cmnd);/* Send lower nibble */


LCD_E = 1; /* Enable pulse */
__delay_us(1000);
LCD_E=0;
__delay_us(5000);
}

void LCD_Char (char char_data) /* LCD data write function */


{
LCD_Port(char_data>>4) ;/* Send upper nibble */
LCD_RS = 1; /* Data reg.*/
LCD_E= 1;
__delay_us(1000);
LCD_E= 0;
__delay_us(2000);

LCD_Port (char_data);/* Send lower nibble */


LCD_E=1; /* Enable pulse */
__delay_us(1000);
LCD_E=0;
__delay_us(5000);
}

void LCD_Init (void) /* LCD Initialize function */


{
__delay_us(20000); /* LCD Power ON Initialization time >15ms */
LCD_Command (0x02); /* 4bit mode */
__delay_ms(2);
LCD_Command (0x28); /* Initialization of 16X2 LCD in 4bit mode */
__delay_ms(2);
LCD_Command (0x0C); /* Display ON Cursor OFF */
__delay_ms(2);
LCD_Command (0x06); /* Auto Increment cursor */
__delay_ms(2);
LCD_Command (0x01); /* Clear display */
__delay_ms(3);

LCD_Command (0x80); /* Cursor at home position */


__delay_ms(2);
}

www.rpc.vn Page 19
Training Page 20

Main.c

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/LCD4bit.h"
char LCD_print[20];
uint16_t previous=0;

void main(void)
{
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
LCD_Init();
sprintf(LCD_print, "Bo dem :%u",TMR1_ReadTimer()); //print counter

LCD_gotoxy(0,0);
LCD_String(LCD_print);
while (1)
{
CLRWDT();

if(previous!=TMR1_ReadTimer()) //change and print counter


{
previous = TMR1_ReadTimer();
if(previous==0)
{
LCD_Clear();
}
sprintf(LCD_print, "Bo dem :%u",previous);
LCD_gotoxy(0,0);
LCD_String(LCD_print);
}

if(SW3_GetValue()==0) //reset counter


{
TMR1_StopTimer();
TMR1_WriteTimer(0x00);
TMR1_StartTimer();
}
}

www.rpc.vn Page 20
Training Page 21

III. Điều khiển động cơ DC

Dự án sử dụng driver module điều khiển động cơ DC L298N, BT1, BT2,


BT3
 Nhấn BT1 đảo chiều động cơ DC
 Nhấn BT2 khởi động động cơ DC, giữ BT2 giảm tốc độ động cơ DC
theo xung PWM cho đến khi dừng hoàn toàn
 Nhấn BT3 dừng ngay động cơ DC

Yêu cầu phần cứng


Board UMB1P.0-15376 V 1.0
Động cơ DC giảm tốc độ
Module điều khiển động cơ DC L298N

Yêu cầu phầm mềm


MPLAB X IDE
Sơ đồ nguyên lý của board L298N

Hình 3. 1 Nguyên lý của module L298N

www.rpc.vn Page 21
Training Page 22

Kích thước board và chức năng pin

Hình 3. 2 Kích thước board và chức năng pin của module L298N

Unibus

Hình 3. 3 Nguyên lý của Unibus

Kết nối VDD tới +12V Power


5V tới +5V Power
UNIBUS_PWM/IO tới IN1
UNIBUS_RTS/IO tới IN2
GND tới GND

www.rpc.vn Page 22
Training Page 23

Hướng dẫn lập trình


Các Module sử dụng trong dự án

Hình 3. 4 Các module sử dụng trong dự án điều khiển động cơ

Cấu hình Pin Manager: Grid View

Hình 3. 5 Cấu hình Pin Manager Gird View của dự án điều khiển động cơ

Cấu hình Interrupt Module

Hình 3. 6 Cấu hình Interrupt Module của dự án điều khiển động cơ

www.rpc.vn Page 23
Training Page 24

Cấu hình Pin Module

Hình 3. 7 Cấu hình Pin Module của dự án điều khiển động cơ

Cấu hình Interrupt Module

Hình 3. 8 Cấu hình Interrupt module của dự án điều khiển động cơ

Cấu hình Module PWM4

Hình 3. 9 Cấu hình module PWM4 của dự án điều khiển động cơ

www.rpc.vn Page 24
Training Page 25

Cấu hình module PWM3 cấu hình tương tự module PWM4

Cấu hình Timer2 Module

Hình 3. 10 Cấu hình Module Timer2 của dự án điều khiển động cơ

Main.c
#include "mcc_generated_files/mcc.h"
void main(void)
{
SYSTEM_Initialize();
while (1)
{
CLRWDT();
if(SW1_GetValue()==0) //reverse motor
{
if(((uint16_t)(PWM3DCH << 2) | (uint16_t)(PWM3DCL>>6))<=0)
{
PWM3_LoadDutyValue((uint16_t)(PWM4DCH << 2) | (uint16_t)(PWM4DCL>>6));
PWM4_LoadDutyValue(0x00);
}

www.rpc.vn Page 25
Training Page 26

else
{
PWM4_LoadDutyValue((uint16_t)(PWM3DCH << 2) | (uint16_t)(PWM3DCL>>6));
PWM3_LoadDutyValue(0x00);
}
__delay_ms(500);
}

if(SW2_GetValue()==0) //start and reduce speed motor


{
uint16_t state1 = (uint16_t)(PWM3DCH << 2) | (uint16_t)(PWM3DCL>>6);
uint16_t state2 = (uint16_t)(PWM4DCH << 2) | (uint16_t)(PWM4DCL>>6);
if(state1 <= 0 && state2 <= 0 )
{
PWM3_LoadDutyValue(0x3FF); // Speed maximum
}
else if((int16_t)state1 > 0)
{
PWM3_LoadDutyValue(state1 - 3);
}
else if((int16_t)state2 > 0)
{
PWM4_LoadDutyValue(state2 - 3);
}
else
{
PWM3_LoadDutyValue(0x00);
PWM4_LoadDutyValue(0x00);
}
__delay_ms(40);
}

if(SW3_GetValue()==0) // stop motor


{
PWM3_LoadDutyValue(0x00);
PWM4_LoadDutyValue(0x00);
}
}
}

www.rpc.vn Page 26
Training Page 27

IV. Truyền thông nối tiếp

1. I2C sensor RPR-0521RS

Dự án sử dụng module Light & Proximity REV 01 trên module có cảm


biến ánh sáng và tiệm cận RPR-0521RS. Trong dự án chỉ sử dụng cảm
biến tiệm cận khi vật cản ở khoảng cách đủ gần cảm biến LED1 sẽ sáng.
Yêu cầu phần cứng
Board UMB1P.0-15376 V 1.0
Module Light & Proximity REV 01
Yêu cầu phầm mềm
MPLAB X IDE

Giới thiệu sơ lược về cảm biến RPR-0521RS

Cảm biến ánh sáng xung quanh và cảm biến tiệm cận Mô-đun này bao gồm
cảm biến ánh sáng xung quanh, cảm biến tiệm cận quang học và đèn LED hồng
ngoại. Nó cho phép giảm mức tiêu thụ hiện tại và / hoặc cải thiện khả năng
hiển thị của màn hình trong môi trường sáng.

www.rpc.vn Page 27
Training Page 28

Hình 4. 1 Phác thảo package của RPR-0521RS

Hình 4. 2 Sơ đồ khối của RPR-0521RS

www.rpc.vn Page 28
Training Page 29

Hình 4. 3 Hình ảnh module Light & Proximity

Hướng dẫn lập trình


Chọn các module cho dự án

Hình 4. 4 Các module sử dụng trong dự án I2C sensor RPR-0521RS

www.rpc.vn Page 29
Training Page 30

Cấu hình Pin Manager

Hình 4. 5 Cấu hình Pin Manager của dự án I2C sensor RPR-0521RS


Cấu hình Pin Module

Hình 4. 6 Cấu hình Pin Module của dự án I2C sensor RPR-0521RS

Cấu hình Module EUSART1

Hình 4. 7 Cấu hình module EUSART1 của dự án I2C sensor RPR-0521RS

www.rpc.vn Page 30
Training Page 31

Cấu hình Module MSSP1

Hình 4. 8 Cấu hình Module MSSP1 của dự án I2C sensor RPR-0521RS

Khai báo địa chỉ giao tiếp I2C với RPR-0521RS sensor :

#define RPR_0521RS_ADDRESS 0x38

Định dạng ghi dữ liệu

Hàm ghi dữ liệu vào cảm biến :


void WritedataProximitySensor(uint8_t transmitt, uint8_t pointer_reg)
{
uint8_t send[2];
uint8_t send2;
send[0]= pointer_reg;
send[1]= transmitt;
I2C1_WriteNBytes(RPR_0521RS_ADDRESS, send, 2);
}

Định dạng đọc dữ liệu

www.rpc.vn Page 31
Training Page 32

Hàm đọc dữ liệu từ cảm biến :

void GetdataProximitySensor(uint8_t receive[], uint8_t pointer_reg , uint8_t length)


{
uint8_t send;
send= pointer_reg;
I2C1_WriteNBytes(RPR_0521RS_ADDRESS, &send, 1);
I2C1_ReadNBytes(RPR_0521RS_ADDRESS, receive, length);
}

Khởi tạo cảm biến

www.rpc.vn Page 32
Training Page 33

Hàm khởi tạo cảm biến


void Proximity_Sensor_Init (void)
{
WritedataProximitySensor(0x52, 0x41);
WritedataProximitySensor(0x00, 0x4A);
}

Hàm khởi tạo ngắt trên pin INT


void Proximity_Interupt_Init (uint8_t reg_value)
{
WritedataProximitySensor(reg_value, 0x4A);
}

Cấu hình Threshsold High

void Set_PS_ThresholdHigh(uint16_t value)


{
WritedataProximitySensor(value & 0xFF, 0x4B);
WritedataProximitySensor(value >>8, 0x4C);
}

Cấu hình Threshshould Low

void Set_PS_ThresholdLow(uint16_t value)


{
WritedataProximitySensor(value & 0xFF, 0x4D);
WritedataProximitySensor(value >>8, 0x4E);
}

www.rpc.vn Page 33
Training Page 34

Main.c
#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"
#define RPR_0521RS_ADDRESS 0x38
uint8_t getdata[10];

void GetdataProximitySensor(uint8_t receive[], uint8_t pointer_reg , uint8_t length)


{
uint8_t send;
send= pointer_reg;
I2C1_WriteNBytes(RPR_0521RS_ADDRESS, &send, 1);
I2C1_ReadNBytes(RPR_0521RS_ADDRESS, receive, length);
}

void WritedataProximitySensor(uint8_t transmitt, uint8_t pointer_reg)


{
uint8_t send[2];
uint8_t send2;
send[0]= pointer_reg;
send[1]= transmitt;
//I2C1_WriteNBytes(RPR_0521RS_ADDRESS, &send, 1);
I2C1_WriteNBytes(RPR_0521RS_ADDRESS, send, 2);
}

void Proximity_Sensor_Init (void)


{
WritedataProximitySensor(0x52, 0x41);
WritedataProximitySensor(0x00, 0x4A);
}

void Proximity_Interupt_Init (uint8_t reg_value)


{
WritedataProximitySensor(reg_value, 0x4A);
}

void Set_PS_ThresholdHigh(uint16_t value)


{
WritedataProximitySensor(value & 0xFF, 0x4B);
WritedataProximitySensor(value >>8, 0x4C);
}

void Set_PS_ThresholdLow(uint16_t value)


{
WritedataProximitySensor(value & 0xFF, 0x4D);
WritedataProximitySensor(value >>8, 0x4E);
}

www.rpc.vn Page 34
Training Page 35

void main(void)
{

// initialize the device


SYSTEM_Initialize();

printf("Hello\n");
Proximity_Sensor_Init();
Proximity_Interupt_Init (0x05);
Set_PS_ThresholdHigh(1500);
__delay_ms(300);
while (1)
{
CLRWDT();
//GetdataProximitySensor(getdata, 0x44, 2);
//printf("%u\n", (getdata[1]<<8) | (getdata[0]));

if(INT_GetValue() == 0)
{
LED1_SetHigh();
}
else
{
LED1_SetLow();
}

__delay_ms(300);

}
}

Lưu ý : Khi Generate, MCC không tự include header


“mcc_generated_files/examples/i2c1_master_example.h” vào file
main.c khi lập trình chúng ta phải thêm header này vào

#include “mcc_generated_files/examples/i2c1_master_example.h”

www.rpc.vn Page 35
Training Page 36

2. ADC Sensor

Dự án sử dụng phototransistor RPM-075PTT86(Q5 trên board) khi ánh


sáng chiếu vào phototransistor càng lớn giá trị ADC đọc được càng nhỏ và
ngược lại. Giá trị ADC được hiển thị trên Advcance Serial Port Terminal
mỗi 200ms qua giao tiếp cổng COM với máy tính. Khi giá trị ADC nhỏ
hơn 100, in lên Terminal “Detect light”.
 Yêu cầu phần cứng
Board UMB1P.0-15376 V 1.0
Cáp Micro USB
 Yêu cầu phầm mềm
MPLAB X IDE
Advcance Serial Port Terminal
 Sơ đồ nguyên lý

Hình 4. 9 Nguyên lý của dự án ADC sensor

Hình 4. 10 Phototrasistor(Q5) trên board

www.rpc.vn Page 36
Training Page 37

Hướng dẫn lập trình

Các module cần dùng trong dự án

Hình 4. 11 Các module cần dùng cho dự án ADC Sensor

Cấu hình Pin Manager

Hình 4. 12 Cấu hình Pin Manager của dự án ADC Sensor

Cấu hình Pin Module

Hình 4. 13 Cấu hình Pin Module của dự án ADC Sensor

www.rpc.vn Page 37
Training Page 38

Cấu hình ADC

Hình 4. 14 Cấu hình ADC của dự án ADC Sensor

Cấu hình module EUSART

Hình 4. 15 Cấu hình module EUSART của dự án ADC Sensor

www.rpc.vn Page 38
Training Page 39

Main.c
#include "mcc_generated_files/mcc.h"
uint16_t result_ADC;
/*
Main application
*/
void main(void)
{
SYSTEM_Initialize();

while (1)
{
CLRWDT();
// Add your application code
result_ADC = ADC_GetConversion(channel_ANB4); // Đọc ADC
printf("%u\n",result_ADC); // in ra giá trị đọc được
if(result_ADC <= 100 )
{
printf("Detect light\n");

}
__delay_ms(200);
}
}

www.rpc.vn Page 39
Training Page 40

3. EEPROM 25AA1024

Dự án sử dụng EEPROM để đọc/ghi dữ liệu vào EEPROM và thực hiện 1


số chức năng đơn giản. Giao tiếp với EEPROM được thực hiện qua cổng
COM của máy tính.
Yêu cầu phần cứng
Board UMB1P.0-15376 V 1.0
Cáp Micro USB
Module EEPROM 25AA1024T-I/SM
Yêu cầu phầm mềm
MPLAB X IDE
Advcance Serial Port Terminal

Hình 4. 16 Package và chức năng pin của EEPROM 25AA1024

Hình 4. 17 Sơ đồ khối của EEPROM 25AA1024

www.rpc.vn Page 40
Training Page 41

Hình 4. 18 Hình ảnh của module EEPROM 25AA1024

Các Module sử dụng trong dự án

Hình 4. 19 Các module sử dụng trong dự án EEPROM 25AA1024

www.rpc.vn Page 41
Training Page 42

Cấu hình Pin Manager

Hình 4. 20 Cấu hình Pin Manager của dự án EEPROM 25AA1024

Cấu hình Pin Module

Hình 4. 21 Cấu hình Pin Module của dự án EEPROM 25AA1024

Cấu hình Module Interrupt

Hình 4. 22 Cấu hình Interrupt Module của dự án EEPROM 25AA1024

www.rpc.vn Page 42
Training Page 43

Cấu hình EUSART1


Hình 4. 23 Cấu hình module EUSART1 của dự án EEPROM 25AA1024

Cấu hình MSSP1

Hình 4. 24 Cấu hình module MSSP1 của dự án EEPROM 25AA1024

www.rpc.vn Page 43
Training Page 44

Cấu hình bit hướng dẫn

Hình 4. 25 Cấu hình các bit hướng dẫn của EEPROM 25AA1024

Cấu hình trình tự read

Hàm cấu hình trình tự read

void Read_Sequence(uint32_t address_start, uint8_t data_out[], uint16_t length )


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000011);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
for(int i=0;i<length;i++)
{
data_out[i] = SPI1_ExchangeByte(0x00);
}
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();

www.rpc.vn Page 44
Training Page 45

Cấu hình trình tự write theo byte

Hàm cấu hình trình tự write


void Write_Sequence(uint32_t address_start, uint8_t data_in[], uint16_t length )
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000010);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
for(int i=0;i<length;i++)
{
SPI1_ExchangeByte(data_in[i]);
}
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}
Định dạng read thanh ghi trạng thái

Đọc trạng thái thanh ghi

www.rpc.vn Page 45
Training Page 46

uint8_t Read_StatusRegister(void)
{
uint8_t Stt;
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000101);
Stt = SPI1_ExchangeByte(0x00);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
return Stt;
}

Định dạng write thanh ghi trạng thái

www.rpc.vn Page 46
Training Page 47

void Write_StatusRegister(uint8_t setup)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000001);
SPI1_ExchangeByte(setup);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

Các hàm xóa dữ liệu trong EEPROM


void Page_Erase (uint32_t address_start)
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b01000010);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}
void Sector_Erase (uint32_t address_start)
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b11011000);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();

www.rpc.vn Page 47
Training Page 48

}
void Chip_Erase (void)
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b11000111);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

Hàm hiển thị dòng lệnh


void Show_INS(void)
{
printf("1. Read from EEPROM : read( < start position> , < number of memory cell> ) Ex:
read(3,7) \n");
printf("2. Write to EEPROM : write( < start position> , < string data> ) Ex: write(4,R&P
Electronic) Max string = 64 \n");
printf("3. Page erase : erase_page( < position cell in page> ) Ex: erase_page(3) or
erase_page(512) \n");
printf("4. Sector erase : erase_sector( < position cell in sector>) Ex: erase_sector(0) or
erase_sector(4096) \n");
printf("5. Chip erase : erase_chip() Ex: erase_chip()\n");
printf("6. Read status register : read_status() Ex: read_status()\n");
printf("7. Write status : write_status( < value to set> ) Ex: write_status(0b10000000) \n");
printf("8. Check ID : check ID Show Manufacturers_ID \n");
}

Main.c
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include <string.h>
#define FALSE_SYNTAX_ADDRESS 1
#define FALSE_SYNTAX_DATA 2
#define FALSE_SYNTAX_LENGTH 3
#define DATA_EMPTY 4
#define FALSE_SYNTAX_REG_VALUE 5

char receive[64];
uint8_t receive_SPI[64];
uint8_t transmitt_SPI[64];
uint32_t addressUART=0;
uint8_t dataUART[64];
uint8_t datareg=0;
uint16_t lengthUART;

www.rpc.vn Page 48
Training Page 49

uint8_t error1;
uint8_t error2;
uint8_t error3;
uint8_t error4;

void receive_uart (char receivedata[])


memset(receivedata,'\0',64);
if(EUSART1_is_rx_ready()== true)
{
//while(EUSART1_is_rx_ready()== true)
memset(receivedata,'\0',64);
{
uint8_t tail= eusart1RxCount;
for(int i=0;i < tail;i++)
{
receivedata[i]=EUSART1_Read();
}
}
printf("%s\n",receivedata);
}
}

void EEPROM_Init(void) //set up EEPROM


{
CS_SetHigh();
HOLD_SetHigh();
WP_SetHigh();
}
void Read_Sequence(uint32_t address_start, uint8_t data_out[], uint16_t length )
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000011);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
for(int i=0;i<length;i++)
{
data_out[i] = SPI1_ExchangeByte(0x00);
}

www.rpc.vn Page 49
Training Page 50

CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

void Write_Sequence(uint32_t address_start, uint8_t data_in[], uint16_t length ) //Ghi dữ


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000010);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
for(int i=0;i<length;i++)
{
SPI1_ExchangeByte(data_in[i]);
}
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

uint8_t Read_Manufacturers_ID(void) //Đọc ID EEPROM


{
uint8_t ID=33;
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b10101011);
SPI1_ExchangeByte(0x00);
SPI1_ExchangeByte(0x00);
SPI1_ExchangeByte(0x00);
ID = SPI1_ExchangeByte(0x00);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
return ID;
}

uint8_t Read_StatusRegister(void) //Đọc trạng thái từ thanh ghi


{
uint8_t Stt;
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000101);
Stt = SPI1_ExchangeByte(0x00);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
return Stt;
}

www.rpc.vn Page 50
Training Page 51

void Write_StatusRegister(uint8_t setup) //Ghi trạng thái vào thanh ghi


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000001);
SPI1_ExchangeByte(setup);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

void Write_Enable(void) //Cho phép ghi


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b00000110);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

void Page_Erase (uint32_t address_start) //Xóa trang


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b01000010);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

void Sector_Erase (uint32_t address_start) //Xóa khu vực


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(0b11011000);
SPI1_ExchangeByte((uint8_t)(address_start>>16));
SPI1_ExchangeByte((uint8_t)((address_start&0xFF00)>>8));
SPI1_ExchangeByte((uint8_t)(address_start));
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

void Chip_Erase (void) //Xóa toàn bộ chip EEPROM


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();

www.rpc.vn Page 51
Training Page 52

SPI1_ExchangeByte(0b11000111);
CS_SetHigh();
__delay_ms(100); // Trel >100us
SPI1_Close();
}

uint8_t TakeAddressFromUART(char in[], uint32_t *out) //Nhận địa chỉ từ UART


{
int i=0;
char *start;
int t=0;
uint8_t typenum=0;
*out=0;
start = strstr(receive, "0x");
if(start != NULL)
{
typenum=1;
}
start = strstr(receive, "0b");
if(start!=NULL)
{
typenum=2;
}
while((start != &in[i])&&i<64)
{
i++;
}
if(start == NULL)
{
i=0;
while((in[i]<'0'||in[i]>'9')&& i<64 && in[i-1] !='(')
{
i++;
}
}

if(typenum==1)
{
i=i+2;
t=i;
while(t<64&&in[t]!=',')
{
if((in[t]<'0'||in[t]>'9')&&(in[i]<'A'|| in[i]>'F')&&(in[i]<'a'|| in[i]>'f'))
{
return FALSE_SYNTAX_ADDRESS;
}
t++;
}
while(((in[i]>='0'&& in[i]<='9')||(in[i]>='A'&& in[i]<='F')||(in[i]>='a'&& in[i]<='f'))&&i<64)
{
char img_in = in[i];

www.rpc.vn Page 52
Training Page 53

switch(img_in)
{
case 'A':
img_in = 10+48;
break;
case 'B':
img_in = 11+48;
break;
case 'C':
img_in = 12+48;
break;
case 'D':
img_in = 13+48;
break;
case 'E':
img_in = 14+48;
break;
case 'F':
img_in = 15+48;
break;
case 'a':
img_in = 10+48;
break;
case 'b':
img_in = 11+48;
break;
case 'c':
img_in = 12+48;
break;
case 'd':
img_in = 13+48;
break;
case 'e':
img_in = 14+48;
break;
case 'f':
img_in = 15+48;

break;
default:
break;
}
*out = *out*16 + (uint32_t)(img_in-48);
i++;
}
}
else if(typenum == 2)
{
i=i+2;
t=i;
while(t<64&&in[t]!=',')

www.rpc.vn Page 53
Training Page 54

{
if(in[t]<'0' || in[t]>'1')
{
return FALSE_SYNTAX_ADDRESS;
}
t++;
}
while((in[i]>='0'&& in[i]<='1')&&i<64)
{
*out = *out*2 + (uint32_t)(in[i]-48);
i++;
}
}
else
{
t=i;
while(t<64&&in[t]!=',')
{
if(in[t]<'0' || in[t]>'9')
{
return FALSE_SYNTAX_ADDRESS;
}
t++;
}
if(t==i)
{
return FALSE_SYNTAX_ADDRESS;
}
while((in[i]>='0'&& in[i]<='9')&&i<64)
{
*out = *out*10 + (uint32_t)(in[i]-48);
i++;
}
}
return 0;
}

uint8_t TakeDataFromUART(char in[], uint8_t out[]) //Nhận dữ liệu từ UART


{
int i = 0;
int j = 0;
int first = 0;
memset(out,'\0',64);
while((i<64 && in[i]!=')'))
{
if(in[i]==',')
{
first = i;
i++;
j=0;
}

www.rpc.vn Page 54
Training Page 55

if(first>0)
{
if(in[i]>='0'&& in[i]<='9')
{
out[j]= (uint8_t)(in[i]-48);
}
else
{
out[j]= (uint8_t)in[i];
}
}
if(in[i] ==')')
{
j=0;
}
else
{
j++;
i++;
}
}
if(j<=0)
{
return DATA_EMPTY;
}
else
{
return 0;
}
}

uint8_t TakeLengthFromUART(char in[], uint16_t *out) //Nhận độ dài dữ liệu từ UART


{
int i = 0;
int j = 0;
int first = 0;
*out=0;
while((i<64 && in[i]!=')'))
{
if(in[i]==',')
{
first = i;
i++;
j=0;
}
if(first>0)
{
if(in[i]>='0'&& in[i]<='9')
{
*out=*out*10 + (uint16_t)(in[i]-48);
}

www.rpc.vn Page 55
Training Page 56

else
{
return FALSE_SYNTAX_LENGTH ;
}
}
j++;
i++;
}
return 0;
}

uint8_t TakeStatusDATAFromUART(char in[], uint8_t *out) //Lấy trạng thái dữ liệu từ UART
{
int i=0;
char *start;
int t=0;
uint8_t typenum=0;
*out=0;
start = strstr(receive, "0x");
if(start != NULL)
{
typenum=1;
}
start = strstr(receive, "0b");
if(start!=NULL)
{
typenum=2;
}
while((start != &in[i])&&i<64)
{
i++;
}
if(start == NULL)
{
i=0;
while((in[i]<'0'||in[i]>'9')&& i<64 && in[i-1] !='(')
{
i++;
}
}

if(typenum==1)
{
i=i+2;
t=i;
while(t<64&&in[t]!=')')
{
if((in[t]<'0'||in[t]>'9')&&(in[i]<'A'|| in[i]>'F')&&(in[i]<'a'|| in[i]>'f'))
{
return FALSE_SYNTAX_REG_VALUE;
}

www.rpc.vn Page 56
Training Page 57

t++;
}
while(((in[i]>='0'&& in[i]<='9')||(in[i]>='A'&& in[i]<='F')||(in[i]>='a'&& in[i]<='f'))&&i<64)
{
char img_in = in[i];
switch(img_in)
{
case 'A':
img_in = 10+48;
break;
case 'B':
img_in = 11+48;
break;
case 'C':
img_in = 12+48;
break;
case 'D':
img_in = 13+48;
break;
case 'E':
img_in = 14+48;
break;
case 'F':
img_in = 15+48;
break;
case 'a':
img_in = 10+48;
break;
case 'b':
img_in = 11+48;
break;
case 'c':
img_in = 12+48;
break;
case 'd':
img_in = 13+48;
break;
case 'e':
img_in = 14+48;
break;
case 'f':
img_in = 15+48;
break;
default:
break;
}
*out = *out*16 + (uint8_t)(img_in-48);
i++;
}
}
else if(typenum == 2)

www.rpc.vn Page 57
Training Page 58

{
i=i+2;
t=i;
while(t<64&&in[t]!=')')
{
if(in[t]<'0' || in[t]>'1')
{
return FALSE_SYNTAX_REG_VALUE;
}
t++;
}
while((in[i]>='0'&& in[i]<='1')&&i<64)
{
*out = *out*2 + (uint8_t)(in[i]-48);
i++;
}
}
else
{
t=i;
while(t<64&&in[t]!=')')
{
if(in[t]<'0' || in[t]>'9')
{
return FALSE_SYNTAX_REG_VALUE;
}
t++;
}
if(t==i)
{
return FALSE_SYNTAX_REG_VALUE;
}
while((in[i]>='0'&& in[i]<='9')&&i<64)
{
*out = *out*10 + (uint8_t)(in[i]-48);
i++;
}
}
return 0;
}

void Show_INS(void) //Hiển thị các dòng lệnh


{
printf("1. Read from EEPROM : read( < start position> , < number of memory cell> ) Ex:
read(3,7) \n");
printf("2. Write to EEPROM : write( < start position> , < string data> ) Ex: write(4,R&P
Electronic) Max string = 64 \n");
printf("3. Page erase : erase_page( < position cell in page> ) Ex: erase_page(3) or
erase_page(512) \n");
printf("4. Sector erase : erase_sector( < position cell in sector>) Ex: erase_sector(0) or
erase_sector(4096) \n");

www.rpc.vn Page 58
Training Page 59

printf("5. Chip erase : erase_chip() Ex: erase_chip()\n");


printf("6. Read status register : read_status() Ex: read_status()\n");
printf("7. Write status : write_status( < value to set> ) Ex: write_status(0b10000000) \n");
printf("8. Check ID : check ID Show Manufacturers_ID \n");
}

void main(void)
{
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
EEPROM_Init();
IOCAF5_SetInterruptHandler(PressSPI);
Write_StatusRegister(0b10000000);
Write_Enable();
for(uint8_t i = 0; i<32;i++)
{
transmitt_SPI[i] = i + 32;
}
Write_Sequence(0x00, transmitt_SPI, 32);
printf("hello\n");
printf("//all to show all instruction \n");
while (1)
{
CLRWDT();
receive_uart (receive);
char *read_check = strstr(receive,"read(");
char *write_check = strstr(receive,"write(");
char *read_status_check = strstr(receive,"read_status(");
char *write_status_check = strstr(receive,"write_status(");
char *page_erase_check = strstr(receive,"erase_page(");
char *sector_erase_check = strstr(receive,"erase_sector(");
char *chip_erase_check = strstr(receive,"erase_chip(");
char last = receive[strlen(receive)-1];

if(strcmp(receive,"check ID") == 0) //check ID


{
uint8_t ID = Read_Manufacturers_ID();
if(ID == 0x29)
{
printf("ID 25AA1024T is : %u %s\n", ID, " true");
}
else
{
printf("ID 25AA1024T is : %u %s\n", ID, " false");
}
}

else if(read_check == &receive[0] && last ==')') //check read


{

www.rpc.vn Page 59
Training Page 60

error1 = TakeAddressFromUART(receive, &addressUART);


error2 = TakeLengthFromUART(receive, &lengthUART);
if(error1 == FALSE_SYNTAX_ADDRESS )
{
printf("!FALSE_SYNTAX_ADDRESS\n");
}
else if(error2 == FALSE_SYNTAX_LENGTH)
{
printf("!FALSE_SYNTAX_LENGTH\n");
}
else
{
Read_Sequence(addressUART, receive_SPI, lengthUART);
printf("ok\n");
for(int i=0;i < strlen((char*)receive_SPI);i++)
{
printf("Value read %u\n",receive_SPI[i]);
}
}
}

else if(write_check == &receive[0] && last ==')') //check write


{
error1 = TakeAddressFromUART(receive,&addressUART);
error3 = TakeDataFromUART(receive, dataUART);
if(error1 == FALSE_SYNTAX_ADDRESS)
{
printf("!FALSE_SYNTAX_ADDRESS\n");
}
else if(error3 == DATA_EMPTY)
{
printf("!DATA_EMPTY\n");
}
else
{
Write_Enable();
Write_Sequence(addressUART, dataUART, strlen((char*)dataUART));
printf("ok\n");
}
}

else if(page_erase_check == &receive[0] && last ==')') //check page erase


{
error1 = TakeAddressFromUART(receive,&addressUART);
if(error1 == FALSE_SYNTAX_ADDRESS)
{
printf("!FALSE_SYNTAX_ADDRESS\n");
}
else
{
Write_Enable();

www.rpc.vn Page 60
Training Page 61

Page_Erase(addressUART);
printf("ok\n");
}
}

else if(sector_erase_check == &receive[0] && last ==')') //check sector erase


{
error1 = TakeAddressFromUART(receive,&addressUART);
if(error1 == FALSE_SYNTAX_ADDRESS)
{
printf("!FALSE_SYNTAX_ADDRESS\n");
}
else
{
Write_Enable();
Sector_Erase(addressUART);
printf("ok\n");
}
}

else if(chip_erase_check == &receive[0] && last ==')') //check chip erase


{
Write_Enable();
Chip_Erase();
printf("ok\n");
}

else if(read_status_check == &receive[0] && last ==')') //check read status


{
printf("ok\n");
printf("%u Status Register Value : \n",Read_StatusRegister());
}
else if(write_status_check == &receive[0] && last ==')') //check write status
{
error4 = TakeStatusDATAFromUART(receive, &datareg);
if(error4 == FALSE_SYNTAX_REG_VALUE)
{
printf("!FALSE_SYNTAX_REG_VALUE\n");
}
else
{
Write_Enable();
Write_StatusRegister(datareg);
printf("ok\n");
}
}

else if(strcmp(receive,"//all") == 0) //show INS


{
Show_INS();
}

www.rpc.vn Page 61
Training Page 62

else if(strlen(receive) != 0) //false


{
printf("!SYNTAX_INSTRUCTION\n");
}
__delay_ms(300);
}
}

4. I2C_RTCC_MCP7941x

Dự án sử dụng LCD 16x2 hiển thị thời gian thực của module RTCC, trong
dự án này chỉ gồm giờ, phút, giây.
Nhấn BT1 cho phép điều chỉnh thời gian thực bằng tay.
Nhấn BT2 thay đổi con trỏ điều chỉnh thời gian từ giờ -> phút -> giây.
Nhấn BT3 thay đổi thời gian của RTCC: giờ(0 -> 23),
phút(0 -> 59), giây(0 -> 59).
Nhấn giữ BT1 xác nhận thời gian mới đã chỉnh sửa.
Yêu cầu phần cứng
Board UMB1P.0-15376 V 1.0
LCD 16x2
Module RTC MCP79410
Yêu cầu phầm mềm
MPLAB X IDE

Sơ đồ nguyên lý và chức năng Pin của Module MCP79410

www.rpc.vn Page 62
Training Page 63

Hình 4. 26 Sơ đồ nguyên lý và chức năng Pin của Module MCP79410

Sơ đồ khối của chip MCP74910

www.rpc.vn Page 63
Training Page 64

Hình 4. 27 Sơ đồ khối của MCP79410

Hình 4. 28 Hình ảnh module RTC MCP79410

www.rpc.vn Page 64
Training Page 65

Hướng dẫn lập trình


Các module sử dụng trong dự án

Hình 4. 29 Các Module sử dụng trong dự án RTC MCP79410

Cấu hình Pin Manager

Hình 4. 30 Cấu hình Pin Manager của dự án RTC MCP79410

Cấu hình Pin Module

www.rpc.vn Page 65
Training Page 66

Hình 4. 31 Cấu hình Pin Module của dự án RTC MCP79410

Cấu hình Interrupt Module

Hình 4. 32 Cấu hình Interrupt Module của dự án RTC MCP79410

Cấu hình Module Timer2

www.rpc.vn Page 66
Training Page 67

Hình 4. 33 Cấu hình Module Timer2 của dự án RTC MCP79410

Cấu hình Module MSSP1

Hình 4. 34 Cấu hình Module MSSP1 của dự án RTC MCP79410

Cấu hình Module EUSART1

www.rpc.vn Page 67
Training Page 68

Hình 4. 35 Cấu hình module EUSART1 của dự án RTC MCP79410

Định dạng byte điều khiển

#define ADDRESSRead_RTCC_MCP7941x 0b1101111


#define ADDRESSWrite_RTCC_MCP7941x 0b1101111

Các thanh ghi cấu hình giá trị giây,giờ, phút của đồng hồ

www.rpc.vn Page 68
Training Page 69

void RTCC_MCP7941x_Settime(uint8_t hour,uint8_t minute, uint8_t second, uint8_t data[4])


{

www.rpc.vn Page 69
Training Page 70

data[0] = 0x00;
data[1] = (uint8_t)((second/10)<<4) | (uint8_t)(second % 10);
data[2] = (uint8_t)((minute/10)<<4) | (uint8_t)(minute % 10);
data[3] = (uint8_t)((hour/10)<<4) | (uint8_t)(hour % 10);
I2C1_WriteNBytes( ADDRESSWrite_RTCC_MCP7941x , data, 4);
}

Hàm cho phép sử dụng OSC


void RTCC_MCP7941x_TriggerOSC(uint8_t trigg)
{
uint8_t send[2];
send[0] = 0x00;
send[1] = ((uint8_t)datasendreg[1] | (uint8_t)(trigg<<7));
I2C1_WriteNBytes( ADDRESSWrite_RTCC_MCP7941x , send , 2);

Thêm vào project file LCD.h và LCD.c đã giới thiệu ở bài training 1.4

Main.c

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c1_master_example.h"
#include "LCD4bit.h"
#include <stdio.h>
uint8_t recieve;
uint8_t datasendreg[4];
uint8_t datareceive[4] = {9, 9, 9, 9};
char printLCD[20];
char printLCD2[2];
uint8_t volatile mode = 0;
uint8_t volatile modetiming = 0;
uint8_t volatile presstiming = 0;
uint8_t volatile kk=0;
uint8_t volatile ss;
#define ADDRESSRead_RTCC_MCP7941x 0b1101111
#define ADDRESSWrite_RTCC_MCP7941x 0b1101111

void RTCC_MCP7941x_Settime(uint8_t hour,uint8_t minute, uint8_t second, uint8_t data[4])


{
data[0] = 0x00;
data[1] = (uint8_t)((second/10)<<4) | (uint8_t)(second % 10);
data[2] = (uint8_t)((minute/10)<<4) | (uint8_t)(minute % 10);
data[3] = (uint8_t)((hour/10)<<4) | (uint8_t)(hour % 10);
I2C1_WriteNBytes( ADDRESSWrite_RTCC_MCP7941x , data, 4);
}

void RTCC_MCP7941x_TriggerOSC(uint8_t trigg)


{
uint8_t send[2];
send[0] = 0x00;
send[1] = ((uint8_t)datasendreg[1] | (uint8_t)(trigg<<7));

www.rpc.vn Page 70
Training Page 71

I2C1_WriteNBytes( ADDRESSWrite_RTCC_MCP7941x , send , 2);


}

void RTCC_MCP7941x_ReadtimeRaw(uint8_t receive[]) // Đọc thời gian từ chip MCP79410


{
uint8_t send[2];
send[0] = 0x00;
I2C1_WriteNBytes( ADDRESSWrite_RTCC_MCP7941x , send , 1);
I2C1_ReadNBytes( ADDRESSRead_RTCC_MCP7941x, receive, 3);
}

void Convert_timeRaw (uint8_t receive[]) //chuyển đổi thời gian


{
receive[0] = (receive[0] & 0x0F) + ((receive[0] & 0x70)>>4)*10;
receive[1] = (receive[1] & 0x0F) + ((receive[1] & 0x70)>>4)*10;
receive[2] = (receive[2] & 0x0F) + ((receive[2] & 0x30)>>4)*10;
}

void mode_value (void)


của giá trị
{
kk++;
if(kk <= 1)
{
TMR2_WriteTimer(0x00);
TMR2_StartTimer();
}
else if (kk >= 2)
{
LCD_Clear();
modetiming=0;
TMR2_StopTimer();
ss = TMR2_ReadTimer();
if(ss > 0x00)
{
mode++;
}
else
{
mode =10;
}
kk=0;
}
if(mode > 1 && mode!=10)
{mode=0;}
}

void main(void)
{
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable();

www.rpc.vn Page 71
Training Page 72

INTERRUPT_PeripheralInterruptEnable();
IOCAF5_SetInterruptHandler(mode_value);
LCD_Init();
printf("Hellooooo\n");
LCD_String_xy(0, 4, "Hello");
RTCC_MCP7941x_Settime(21, 0, 0, datasendreg);
RTCC_MCP7941x_TriggerOSC(1);
__delay_ms(500);
while (1)
{
CLRWDT();

if(mode==0)
{
RTCC_MCP7941x_ReadtimeRaw(datareceive); //read time
Convert_timeRaw(datareceive); //convert time
printf(" %u : %u : %u \n", datareceive[2], datareceive[1], datareceive[0]);
sprintf(printLCD,"%u : %u : %u", datareceive[2], datareceive[1], datareceive[0]);
if(datareceive[0]==0)
{
LCD_Clear();
}
LCD_String_xy(0, 3, printLCD); //print
__delay_ms(50);
}

else if(mode == 10)


{
RTCC_MCP7941x_Settime(datareceive[2], datareceive[1], datareceive[0],
datasendreg); //set time
RTCC_MCP7941x_TriggerOSC(1); //enable OSC
mode=0;
}
else
{
switch (modetiming)
{
case 0 : //hour
{
LCD_Clear();
sprintf(printLCD,"%u : %u : %u", datareceive[2], datareceive[1], datareceive[0]);
LCD_String_xy(0, 3, printLCD);
sprintf(printLCD2,"%c", (char)94);
LCD_String_xy(1, 4, printLCD2);
modetiming++;
break;
}
case 2 : //minute
{

www.rpc.vn Page 72
Training Page 73

LCD_Clear();
sprintf(printLCD,"%u : %u : %u", datareceive[2], datareceive[1], datareceive[0]);
LCD_String_xy(0, 3, printLCD);
sprintf(printLCD2,"%c", (char)94);
LCD_String_xy(1, 8, printLCD2);
modetiming++;
break;
}
case 4 : //sec
{
LCD_Clear();
sprintf(printLCD,"%u : %u : %u", datareceive[2], datareceive[1], datareceive[0]);
LCD_String_xy(0, 3, printLCD);
sprintf(printLCD2,"%c", (char)94);
LCD_String_xy(1, 13, printLCD2);
modetiming++;
break;
}
default:
break;
}
if(SW2_GetValue()==0) //change pointer time
{
modetiming++;
if(modetiming >6)
{
modetiming = 0;
}
__delay_ms(100);
}
if(SW3_GetValue()==0) //change time
{
if(modetiming ==1)
{
datareceive[2]++;
if(datareceive[2]>=24)
{
datareceive[2]=0;
}
modetiming = 0;
}
else if(modetiming ==3)
{
datareceive[1]++;
if(datareceive[1]>=60)
{
datareceive[1]=0;
}
modetiming = 2;
}
else if(modetiming ==5)

www.rpc.vn Page 73
Training Page 74

{
datareceive[0]++;
if(datareceive[0]>=60)
{
datareceive[0]=0;
}
modetiming = 4;
}
__delay_ms(100);
}
}
}
}

V. Truyền thông CAN

Chương trình sau đây mổ tả việc sử dụng giao thức CAN điểu khiển bật tắt các
đèn trên board MCU các đèn LED trên board 1 sẽ được điều khiển các nút
nhấn trên board 2 và ngược lại
Yêu cầu phần cứng
2 board UMB1P.0-15376
2 module CAN MCP2515
Yêu cầu phần mềm
MPLAB IDE
Advcance Serial Port Terminal

www.rpc.vn Page 74
Training Page 75

Hình 5. 1 Module giao tiếp CAN MCP2515

Hình 5. 2 Sơ đồ nguyên lý

Giao thức CAN thông qua module CAN MCP2515 được kết nối với MCU
giao tiếp giữa MCU với module là giao tiếp SPI theo sơ đồ sau :

www.rpc.vn Page 75
Training Page 76

Hình 5. 3 Sơ đồ giao tiếp phần cứng

Hình 5. 4 Kết nối module CAN với board MCU

Kết nối các node với nhau bằng 2 dây theo mô hình CAN_H <–> CAN_H,
CAN_L <–> CAN_L .
Mỗi board module CAN cung cấp 2 cặp cổng CAN_H và CAN_L.

www.rpc.vn Page 76
Training Page 77

Hình 5. 5 Kết nối mạng 2 node CAN

www.rpc.vn Page 77
Training Page 78

IC CAN MCP2515 sử dụng giao tiếp CAN2.0B bao gồm 3 bộ truyền dữ liệu
riêng biệt TXB0 -> TXB3 cho phép truyền dữ liệu độc lập hoặc lần lượt theo
mức độ tiên được người dùng tự cài đặt trong thanh ghi có sẵn. Phần nhận dữ
liệu bao gồm 2 bộ nhận RXB0 và RXB1, mỗi bộ nhận được thiết kế các bộ lọc
tin nhắn, 2 bộ ở bộ nhận RXB0 và 6 ở RXB1(RXB1 có thể sử dụng được 2 bộ
nhận của RXB0) các bộ bọc này kết hợp với 2 mặt nạ lọc RXM0 và RXM1 cho
phép thiết bị chọn thông điệp có liên quan đến node, cách thức tạo độ liên quan
thông điệp người do người dung tự qui định.

Hình 5. 6 Sơ đồ IC giao tiếp CAN MCP2515

Nguyên lý nhận thông điệp(tin nhắn): Các tin nhắn được truyền đi sẽ có trường
định danh Arbitration Field 12 bit ở khung chuẩn và 32 bit ở khung mở rộng,
bộ nhận sẽ so sánh trường này của thông điệp nhận với các bit trong bộ lọc của
bộ nhận để xem xét có nhận thông điệp hay không. Các mặt nạ nhận đùng để
xác định các bit nào trong trường định danh thông điệp được yêu cầu phải khớp
với các bit của bộ lọc. Tuy trường định danh có 12 đến 32 bit nhưng có thể chỉ

www.rpc.vn Page 78
Training Page 79

cần ít hơn số bit này khớp với các vị trí tương ứng của bộ lọc thì thông điệp sẽ
được nhận đây là chức năng của mặt nạ nhận. Xem thêm hình bên dưới.

Hình 5. 7 Nguyên lý mặt nạ nhận

Nếu set 2 bit RXM[1:0] trong thanh ghi RXBxCTRL = 11 mặt nạ nhận và bộ
lọc sẽ bị tắt, bộ nhận sẽ nhận tất cả tin nhắn.

Tóm lượt thanh ghi:


- TRANSMIT BUFFER n CONTROL REGISTER: 1 bit để báo
truyền thông điệp thành công, 1 bit xác định xem thông điệp truyền đi
có mất trường định danh hay không, 1 bit chỉ ra lỗi bus khi truyền, 2 bit
chỉ ra mức độ ưu tiên của bộ đệm truyền, và 1 bit TXREQ set bit này
thành 1 để gửi đi thông điệp nếu thông điệp gửi thành công bit sẽ được
đặt lại 0.
- PIN CONTROL AND STATUS REGISTER: chứa các bit để thiết lập
chức năng cho các chân TXnRTS
các chân này có thể thiết lập để truyền tin nhắn khi tác động logic 0.
- TRANSMIT BUFFER n STANDARD IDENTIFIER REGISTER
HIGH: Các bit cao của ID truyền dạng chuẩn.
- TRANSMIT BUFFER n STANDARD IDENTIFIER REGISTER
LOW: Các bit thấp còn lại của ID chuẩn, 1 bit xác định thông điệp
chuẩn hay mở rộng, 2 bit cao nhất của ID dạng mở rộng.
- TRANSMIT BUFFER n EXTENDED IDENTIFIER 8 REGISTER
HIGH: Chứa 8 bit từ 8 đến 15 của ID mở rộng.
- TRANSMIT BUFFER n EXTENDED IDENTIFIER 0 REGISTER
LOW: 8 bit thấp của ID kiểu mở rộng.
- TRANSMIT BUFFER n DATA LENGTH CODE REGISTER: 1 bit
xác định khung dữ liệu hay khung điều khiển sẽ được truyền, 4 bit quy
định độ dài phần dữ liệu thông điệp truyền.
- TRANSMIT BUFFER n DATA BYTE m REGISTER: Các thanh ghi
này chứa dữ liệu sẽ truyền đi.
- RECEIVE BUFFER n CONTROL REGISTER: 2 bit để bật tắt bộ
lọc và mặt nạ,1 bit cho phép roll over receive, và các bit chỉ ra bộ lọc
được bật.

www.rpc.vn Page 79
Training Page 80

- RXnBF PIN CONTROL AND STATUS REGISTER: Cấu hình chức


năng cho 1 số chân RXBnF trên IC.
- RECEIVE BUFFERn STANDARD IDENTIFIER REGISTER
HIGH: là các thanh ghi chứa các bit cao ID của thông điệp đã nhận
được dạng chuẩn.
- RECEIVE BUFFER n STANDARD IDENTIFIER REGISTER
LOW: thanh ghi chứa các bit thấp của ID dạng chuẩn, bit xác định
khung đữ liệu hay khung điều khiển dạng chuẩn, bit xác định thông điệp
nhận được là đạng khung chuẩn hay mở rộng, 2 bit 16 17 của ID thông
điệp dạng mở rộng nếu có nhận được.
- RECEIVE BUFFER n EXTENDED IDENTIFIER REGISTER
HIGH: Chứa 8 bit ID thông điệp dạng mở rộng từ bit 8 đến 15.
- RECEIVE BUFFER n EXTENDED IDENTIFIER REGISTER
LOW: 8 bit thấp còn lại của khung mở rộng.
- RECEIVE BUFFER n DATA LENGTH CODE REGISTER: Gồm 1
bit chỉ ra khung dữ liệu kiểu mở rộng hay khung điều khiển kiểu mở
rộng, 4 bit để thể hiện độ dài trường dữ liệu của thông điệp nhận được.
- RECEIVE BUFFER n DATA BYTE m REGISTER: Các thanh ghi
này chứa phần dữ liệu của thông điệp nhận được.
- CONFIGURATION REGISTER 1 2 3: Thanh ghi quy định các thức
định thời bit CAN.
- TRANSMIT ERROR COUNTER REGISTER: Bộ đếm lỗi truyền.
- RECEIVE ERROR COUNTER REGISTER: Bộ đếm lỗi nhận.
- ERROR FLAG REGISTER: Thanh ghi cờ báo lỗi nếu có lỗi xảy ra.
- CAN INTERRUPT ENABLE REGISTER: Thanh ghi kích hoạt ngắt.
- CAN INTERRUPT FLAG REGISTER: Thanh ghi cờ báo ngắt.
- CAN CONTROL REGISTER: 3 bit để chon chế độ hoạt động, 1 bit
để huỷ truyền, 1 bit chọn chế độ ONE SHOT, 1 bit cấp xung ra chân
CLKOUT, 2 bit còn lại quy định tần số xung output.
- CAN STATUS REGISTER: Chỉ ra trạng thái hoạt động các loại ngắt
đã xảy ra.

Module được thiết kế để có thể dùng MCU giao tiếp được bằng giao thức SPI
cho tốc độ giao tiếp lên đến 20Mb/s, Một số chức năng có thể được thực hiện
qua lệnh như gửi tin nhắn, lệnh Bit Modify cho phép set rời rạc các bit trong 1
thanh ghi giúp ta đơn giản hoá việc lập trình.

www.rpc.vn Page 80
Training Page 81

Hình 5. 8 Bảng các lệnh giao tiếp SPI

Các module sử dụng trong dự án

Hình 5. 9 Các module sử dụng trong dự án giao thức CAN

www.rpc.vn Page 81
Training Page 82

Cấu hình Pin Manager Gird View

Hình 5. 10 Cấu hình Pin Manager của dự án Giao thức CAN

Cấu hình Pin Module

Hình 5. 11 Cấu hình Pin Module của dự án Giao thức CAN

www.rpc.vn Page 82
Training Page 83

Cấu hình Interrupt Module

Hình 5. 12 Cấu hình Interrupt Module của dự án Giao thức CAN

Cấu hình Module MSSP1

Hình 5. 13 Cấu hình Module MSSP1 của dự án Giao thức CAN

www.rpc.vn Page 83
Training Page 84

Cấu hình Module EUSART1

Hình 5. 14 Cấu hình module EUSART1 của dự án Giao thức CAN

Hướng dẫn lập trình


.
 Định nghĩa các giá trị thường dùng
#define RESET_INS 0b11000000
#define READ 0b00000011
#define WRITE 0b00000010
#define READ_STATUS 0b10100000
#define RX_STATUS 0b10110000
#define BIT_MODIFY 0b00000101
#define READ_RX_BUFFER_SID0 0b10010000
#define READ_RX_BUFFER_DT0 0b10010010
#define READ_RX_BUFFER_DT1 0b10010110
#define READ_RX_BUFFER_SID1 0b10010100
#define LOAD_TX_BUFFER_SID0 0b01000000
#define LOAD_TX_BUFFER_DT0 0b01000001
#define LOAD_TX_BUFFER_SID1 0b01000010
#define LOAD_TX_BUFFER_DT1 0b01000011
#define LOAD_TX_BUFFER_SID2 0b01000100
#define LOAD_TX_BUFFER_DT2 0b01000101
#define REQUEST_TO_SEND_TXBUFF0 0b10000001
#define REQUEST_TO_SEND_TXBUFF1 0b10000010
#define REQUEST_TO_SEND_TXBUFF2 0b10000100

www.rpc.vn Page 84
Training Page 85

#define BIT_MODIFY 0b00000101


Lệnh RESET

void Reset_sensor (void)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(RESET_INS);
CS_SetHigh();
SPI1_Close();
}
 Lệnh READ

void Read_sensor (uint8_t reg, uint8_t *data)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(READ);
SPI1_ExchangeByte(reg);
*data = SPI1_ExchangeByte(0x00);
CS_SetHigh();
SPI1_Close();
}
 Lệnh WRITE

www.rpc.vn Page 85
Training Page 86

void Set_sensor (uint8_t reg, uint8_t data)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(WRITE);
SPI1_ExchangeByte(reg);
SPI1_ExchangeByte(data);
CS_SetHigh();
SPI1_Close();
}

 Lệnh Set từng bit riêng rẽ

void Bit_Modify(uint8_t Address, uint8_t mask, uint8_t dataset)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(BIT_MODIFY);
SPI1_ExchangeByte(Address);
SPI1_ExchangeByte(mask);
SPI1_ExchangeByte(dataset);
CS_SetHigh();
SPI1_Close();
}
 Lệnh yêu cầu buffer truyền

www.rpc.vn Page 86
Training Page 87

void REQUEST_TO_SEND_BUFF (uint8_t buff)


{
uint8_t bufftemp;
switch (buff)
{
case 0: bufftemp = REQUEST_TO_SEND_TXBUFF0;
break;
case 1: bufftemp = REQUEST_TO_SEND_TXBUFF1;
break;
case 2: bufftemp = REQUEST_TO_SEND_TXBUFF2;
break;
default:
break;
}
{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(bufftemp);
CS_SetHigh();
SPI1_Close();
}
 Hàm truyền tin nhắn
void Send_messenger (uint8_t *data, uint8_t buff, uint8_t length)
{
Set_sensor(0x30, 0x03); // Clear TXREQ
Set_sensor(0x35, length);
for(uint8_t i = 0 ; i<length ;i++)
{
Set_sensor(0x36 + i,*data);
data++;
}
REQUEST_TO_SEND_BUFF(buff);
}
Khác với lệnh truyền buffer lệnh này sẽ cấu hình dữ liệu, độ dài dữ liệu sau đó
truyền đi, lệnh truyền buffer chỉ truyền đi data đã có sẵn trong buffer.

 Hàm thiết lập cấu hình ban đầu cho module

Mặc dù module có nhiều hơn 2 bộ cho nhận và truyền nhưng trong ví dụ này ta
chỉ xét với Buffer0 cho cả 2 bộ nhận và truyền
void Sensor_Init (void)
{
// Reset_sensor();
Set_sensor(0x30, 0x00); // Clear TXREQ
Set_sensor(0x31, 0xAA); // Use ID TX type Standard
Set_sensor(0x32, 0xA0); // ID : 0b10101010101
Set_sensor(0x35, 0x08); // Transmitt data frame, data lenght 8 byte
for(uint8_t i=0;i < 8;i++)
{
Set_sensor(0x36 + i,i);

www.rpc.vn Page 87
Training Page 88

}
Set_sensor(0x00, 0xAA); // Use ID RX type Standard
Set_sensor(0x01, 0xA0); // ID : 0b10101010101
Set_sensor(0x20, 0xFF); // Use MASK full bits
Set_sensor(0x21, 0xE0);
Set_sensor(0x2B, 0x01); // Use Interrupt Buffer RX0
Set_sensor(0x2A, 0x0F); // Tq = 0.000004s
Set_sensor(0x0F, 0x07); // Sets Normal Operation mode
}

Để thiết lập các thông số của bộ nhận ta cần xoá bit TXREQ trước khi thực
hiện, mặc định module khi khởi động sẽ ở chế độ cấu hình nên sau khi cài đặt
xong các thông số ta cần đặt module trở lại trạng thái hoạt động bình thường ở
thanh ghi CANCTRL địa chỉ 0x0F. 1 số thanh ghi để thiết lập cần phải đưa
module vào chế độ cấu hình.
Thiết lập báo ngắt khi nhận được tin nhắn, tín hiệu ngắt sẽ báo ra chân INT
module bằng cách kéo chân này xuống thấp nối chân này với các chân IO của
MCU để nhận tín hiệu ngắt.

 Hàm tạo cờ ngắt


void receive_led(void)
{

LED3_Toggle();
receive_flag = ~receive_flag;
}

 Chương trình chính


Điều cần thiết đầu tiên khi lập trình cho Module này mà phải kéo chân STBY
của module xuống mức thấp để module hoạt động bình thường.
Yêu cầu lệnh reset module trước khi khởi động

Reset_sensor();
Sensor_Init ();
STBY_SetLow();
IOCCF7_SetInterruptHandler(receive_led);

Hàm IOCCF7_SetInterruptHandler(receive_led); dùng để tạo ngắt trên chân


MCU nối với module CAN, Hàm này là hàm con trỏ trỏ đến hàm receive_led,
Hàm thực hiện khi chương trình xảy ra ngắt.
if(receive_flag != receive_pre)
{
receive_pre = receive_flag;
uint8_t DLC = 0;
Bit_Modify( 0x2C, 0b00000001, 0x00);
Read_sensor(0x65,&DLC);
for(uint8_t i=0; i < (DLC&0x0F);i++)
{

www.rpc.vn Page 88
Training Page 89

Read_sensor(0x66 + i, &receiveframe[i]);
}
}

Phần này dùng để đọc dữ liệu từ module khi có ngắt nhận xảy ra.
if(SW1_GetValue()==0 && press == 0)
{
Send_messenger(sendframe1,0,8);
press = 1;
}
else if(SW2_GetValue()==0 && press == 0)
{
Send_messenger(sendframe2,0,8);
press = 1;
}
else if (SW3_GetValue()==0 && press == 0)
{
Send_messenger(sendframe3,0,8);
press = 1;
}
else if(SW1_GetValue()== 1 && SW2_GetValue() == 1 &&
SW3_GetValue()== 1)
{
press=0;
}

Phần chương trình dùng để gửi các thông điệp khác nhau theo nút nhấn.
if(strcmp((char*)receiveframe,"abcdefgh")==0)
{
LED1_SetHigh();
LED2_SetLow();
LED3_SetLow();
}
else if (strcmp((char*)receiveframe,"ijklmnop")==0)
{
LED1_SetLow();
LED2_SetHigh();
LED3_SetLow();
}
else if (strcmp((char*)receiveframe,"qrstuvwx")==0)
{
LED1_SetLow();
LED2_SetLow();
LED3_SetLow();
}

www.rpc.vn Page 89
Training Page 90

Phần chương trình sẽ so sánh dữ liệu nhận được với lệnh tương ứng để thực
hiện bật tắt đèn.

Hình 5. 15 Khung truyền dữ liệu CAN

Main.c

#include "mcc_generated_files/mcc.h"
#include <string.h>
#define RESET_INS 0b11000000
#define READ 0b00000011
#define WRITE 0b00000010
#define READ_STATUS 0b10100000
#define RX_STATUS 0b10110000
#define BIT_MODIFY 0b00000101
#define READ_RX_BUFFER_SID0 0b10010000
#define READ_RX_BUFFER_DT0 0b10010010
#define READ_RX_BUFFER_DT1 0b10010110
#define READ_RX_BUFFER_SID1 0b10010100
#define LOAD_TX_BUFFER_SID0 0b01000000
#define LOAD_TX_BUFFER_DT0 0b01000001
#define LOAD_TX_BUFFER_SID1 0b01000010
#define LOAD_TX_BUFFER_DT1 0b01000011
#define LOAD_TX_BUFFER_SID2 0b01000100
#define LOAD_TX_BUFFER_DT2 0b01000101
#define REQUEST_TO_SEND_TXBUFF0 0b10000001
#define REQUEST_TO_SEND_TXBUFF1 0b10000010
#define REQUEST_TO_SEND_TXBUFF2 0b10000100
#define BIT_MODIFY 0b00000101
uint8_t press = 0;
uint8_t receive = 0;
uint8_t sendframe1[8] = "abcdefgh";
uint8_t sendframe2[8] = "ijklmnop";

www.rpc.vn Page 90
Training Page 91

uint8_t sendframe3[8] = "qrstuvwx";


uint8_t receiveframe[9]={0,0,0,0,0,0,0,0,0};
volatile uint8_t receive_flag = 0;
uint8_t receive_pre = 0;

void Reset_sensor (void)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(RESET_INS);
CS_SetHigh();
SPI1_Close();
}

void Set_sensor (uint8_t reg, uint8_t data)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(WRITE);
SPI1_ExchangeByte(reg);
SPI1_ExchangeByte(data);
CS_SetHigh();
SPI1_Close();
}

void Read_sensor (uint8_t reg, uint8_t *data)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(READ);
SPI1_ExchangeByte(reg);
*data = SPI1_ExchangeByte(0x00);
CS_SetHigh();
SPI1_Close();
}

void Bit_Modify(uint8_t Address, uint8_t mask, uint8_t dataset)


{
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(BIT_MODIFY);
SPI1_ExchangeByte(Address);
SPI1_ExchangeByte(mask);
SPI1_ExchangeByte(dataset);
CS_SetHigh();
SPI1_Close();
}

www.rpc.vn Page 91
Training Page 92

void REQUEST_TO_SEND_BUFF (uint8_t buff)


{
uint8_t bufftemp;
switch (buff)
{
case 0:
bufftemp = REQUEST_TO_SEND_TXBUFF0;
break;
case 1:
bufftemp = REQUEST_TO_SEND_TXBUFF1;
break;
case 2:
bufftemp = REQUEST_TO_SEND_TXBUFF2;
break;
default:
break;
}
SPI1_Open(SPI1_DEFAULT);
CS_SetLow();
SPI1_ExchangeByte(bufftemp);
CS_SetHigh();
SPI1_Close();
}

void Sensor_Init (void)


{
// Reset_sensor();
Set_sensor(0x30, 0x00); // Clear TXREQ
Set_sensor(0x31, 0xAA); // Use ID TX type Standard
Set_sensor(0x32, 0xA0); // ID : 0b10101010101
Set_sensor(0x35, 0x08); // Transmitt data frame, data lenght 8 byte
for(uint8_t i=0;i < 8;i++)
{
Set_sensor(0x36 + i,i);
}
Set_sensor(0x00, 0xAA); // Use ID RX type Standard
Set_sensor(0x01, 0xA0); // ID : 0b10101010101
Set_sensor(0x20, 0xFF); // Use MASK full bits
Set_sensor(0x21, 0xE0);
Set_sensor(0x2B, 0x01); // Use Interrupt Buffer RX0
Set_sensor(0x2A, 0x0F); // Tq = 0.000004s
Set_sensor(0x0F, 0x07); // Sets Normal Operation mode
}

void Send_messenger (uint8_t *data, uint8_t buff, uint8_t length)


{
Set_sensor(0x30, 0x03); // Clear TXREQ
Set_sensor(0x35, length);
for(uint8_t i = 0 ; i<length ;i++)
{
Set_sensor(0x36 + i,*data);

www.rpc.vn Page 92
Training Page 93

data++;
}
REQUEST_TO_SEND_BUFF(buff);
}

void receive_led(void)
{

LED3_Toggle();
receive_flag = ~receive_flag;
}

void main(void)
{
SYSTEM_Initialize();
Reset_sensor();
Sensor_Init ();
STBY_SetLow();
IOCCF7_SetInterruptHandler(receive_led);
printf("hello\n");
while (1)
{
CLRWDT();
if(receive_flag != receive_pre)
{
receive_pre = receive_flag;
uint8_t DLC = 0;
Bit_Modify( 0x2C, 0b00000001, 0x00);
Read_sensor(0x65,&DLC);
for(uint8_t i=0; i < (DLC&0x0F);i++)
{
Read_sensor(0x66 + i, &receiveframe[i]);
}
}
if(SW1_GetValue()==0 && press == 0)
{
Send_messenger(sendframe1,0,8);
press = 1;
}
else if(SW2_GetValue()==0 && press == 0)
{
Send_messenger(sendframe2,0,8);
press = 1;
}
else if (SW3_GetValue()==0 && press == 0)
{
Send_messenger(sendframe3,0,8);
press = 1;
}
else if(SW1_GetValue()== 1 && SW2_GetValue() == 1 && SW3_GetValue() == 1)
{

www.rpc.vn Page 93
Training Page 94

press=0;
}
if(strcmp((char*)receiveframe,"abcdefgh")==0)
{
LED1_SetHigh();
LED2_SetLow();
LED3_SetLow();
}
else if (strcmp((char*)receiveframe,"ijklmnop")==0)
{
LED1_SetLow();
LED2_SetHigh();
LED3_SetLow();
}
else if (strcmp((char*)receiveframe,"qrstuvwx")==0)
{
LED1_SetLow();
LED2_SetLow();
LED3_SetLow();
}
}
}

www.rpc.vn Page 94
Training Page 95

Phụ lục

Sử dụng Advcance Serial Port Terminal


Chọn biểu tượng New Session hoặc chọn File -> New Session

Chọn COM kết nối với kit, chọn Baudrate, Data bits, Parity, Stop bits, Flow
control sau đó chọn Open để mở Port

www.rpc.vn Page 95
Training Page 96

Chọn Open port để mở cổng COM

Sau đó màn hình sẽ hiển thị kết quả

Gửi dữ liệu bằng cửa sổ Send :

www.rpc.vn Page 96
Training Page 97

Tài liệu tham khảo

Datasheet MCP2515
https://ww1.microchip.com/downloads/aemDocuments/documents/APID/Prod
uctDocuments/DataSheets/MCP2515-Family-Data-Sheet-DS20001801K.pdf
Datasheet MCP79410
http://ww1.microchip.com/downloads/en/devicedoc/20002266h.pdf
Datasheet 25AA1024
https://ww1.microchip.com/downloads/aemDocuments/documents/MPD/Produ
ctDocuments/DataSheets/1-Mbit-SPI-Bus-Serial-EEPROM-Data-Sheet-
20001836K.pdf
Datasheet RPR-0521RS
https://fscdn.rohm.com/en/products/databook/datasheet/opto/optical_sensor/opt
o_module/rpr-0521rs-e.pdf
L298N Dual H-Bridge Motor Driver User Guide
http://www.handsontec.com/dataspecs/L298N%20Motor%20Driver.pdf

www.rpc.vn Page 97

You might also like