PDA

View Full Version : dsPIC Tutorial 4-Module UART và I2C


namqn
18-09-2006, 08:27 PM
Tutorial 4 cho dsPIC, viết bằng ASM30 lẫn C30, giới thiệu các module UART và I2C (chế độ master). Các ví dụ về module UART thực hiện giao tiếp với máy tính. Các ví dụ về module I2C thực hiện giao tiếp với vi mạch thời gian thực DS1307.

Tập tin "Vidu4.zip" gồm các tập tin nguồn hợp ngữ và .hex. Tập tin "Vidu4C30.zip" gồm các tập tin nguồn C và .hex.

Thân,

ntuan
05-08-2007, 04:17 PM
anh nam ơi , em đã nạp thử chương trình của anh . NHưng khi hiển thị trên máy tính toàn kí tự lạ thôi , không ra được chữ hello . Anh tự lập trình chương trình nhận trên máy ạ . Cách thức nhận như thế nào hả anh ..

namqn
05-08-2007, 06:38 PM
anh nam ơi , em đã nạp thử chương trình của anh . NHưng khi hiển thị trên máy tính toàn kí tự lạ thôi , không ra được chữ hello . Anh tự lập trình chương trình nhận trên máy ạ . Cách thức nhận như thế nào hả anh ..
Tôi chỉ dùng Hyper Terminal của Windows để thử thôi, không có gì đặc biệt. Bạn chú ý là code chương trình sẽ tương ứng với baud rate = 38400 bps, không dùng parity, 1 stop bit khi chạy ở tần số clock = 32 MHz (chip được cấu hình là dùng bộ dao động nội FRC với 4x PLL). Với dsPIC30F4012 mà tôi có, tần số dao động của chip là 8 MHz.

Bạn kiểm tra lại xem cấu hình của Terminal đã phù hợp hay chưa.

Thân,

ntuan
06-08-2007, 05:21 PM
cấu hình truyền nhận em chọn baud rate = 38400 bps (mắc lỗi 0,16% ở tốc độ truyền này ). Nhưng khi em dùng chương trình truyền 1 số từ PC và gửi trả lên PC . Chỉ khi gửi các chữ số xuống thì nhận lại đúng 100% còn khi gửi các kí tự , chữ cái thì bị trả về giá trị sai hết.

namqn
06-08-2007, 06:13 PM
cấu hình truyền nhận em chọn baud rate = 38400 bps (mắc lỗi 0,16% ở tốc độ truyền này ). Nhưng khi em dùng chương trình truyền 1 số từ PC và gửi trả lên PC . Chỉ khi gửi các chữ số xuống thì nhận lại đúng 100% còn khi gửi các kí tự , chữ cái thì bị trả về giá trị sai hết.
Bạn có thể post phần code của mình lên không. Về nguyên tắc, nếu code của bạn chỉ lặp lại những gì đã nhận được từ PC thì không có lý nào nó lại chạy đúng với một số mã và chạy sai với những mã khác. Có lẽ vấn đề nằm trong code cho dsPIC của bạn, cũng có thể là bạn thiết lập cấu hình cho Terminal chưa chính xác (tôi đã nêu đầy đủ thông tin về baud rate, parity, và stop bit).

Thân,

scentoflove
18-08-2007, 02:05 AM
Anh Nam ơi, trong phần i2c hàm read_i2c sau khi set bit RCEN anh gọi wait_i2c và sau khi send ack a cũng gọi wait_i2c. Em sử dụng trên dspic33fj256GP710 thì bị treo 2 chổ đó. Em bỏ đi thì không bị treo nữa.
Anh giải thích dùm em chổ này.

namqn
18-08-2007, 03:03 AM
Anh Nam ơi, trong phần i2c hàm read_i2c sau khi set bit RCEN anh gọi wait_i2c và sau khi send ack a cũng gọi wait_i2c. Em sử dụng trên dspic33fj256GP710 thì bị treo 2 chổ đó. Em bỏ đi thì không bị treo nữa.
Anh giải thích dùm em chổ này.
Code của tôi viết cho dsPIC30F4012 chỉ có 1 module I2C, nên trong Wait_I2C() kiểm tra cờ _MI2CIF, còn chip của bạn có 2 module với cách gọi tên các cờ ngắt tương ứng khác đi. Đúng ra thì khi bạn dùng code cũ của tôi cho dsPIC33FJ256GP710 thì phải nhận được thông báo lỗi khi biên dịch mới đúng. Bạn sửa lại tên bit cần kiểm tra cho đúng (_MI2C1IF hay _MI2C2IF) trong hàm Wait_I2C() là có thể dùng với chip của bạn.

Thân,

scentoflove
18-08-2007, 05:50 PM
Cái này em có sửa rồi đúng với thanh ghi cũng như cờ ngắt, hàm wait_i2c() hoạt động bình thường, hàm write_i2c() gọi wait_i2c() vẫn chạy được khi em xuất dữ liệu ra nhưng read_i2c() thì bị treo

namqn
18-08-2007, 06:41 PM
Cái này em có sửa rồi đúng với thanh ghi cũng như cờ ngắt, hàm wait_i2c() hoạt động bình thường, hàm write_i2c() gọi wait_i2c() vẫn chạy được khi em xuất dữ liệu ra nhưng read_i2c() thì bị treo
Trong trường hợp này tôi chưa có đủ thông tin. Vì khi đọc từ ngoại vi thì thông thường master sẽ ghi ra trước rồi tạo RESTART, sau đó mới đọc về từ ngoại vi. Theo tài liệu dsPIC33F FRM - Section 19 về I2C thì sau cạnh xuống của xung clock thứ 8 thì module cũng sẽ bật cờ ngắt MI2CxIF, do đó theo tôi phần wait_i2c() vẫn có thể được dùng để phát hiện thời điểm hoàn tất việc nhận từ ngoại vi. Bạn nên post phần code đó để tiện phân tích. Chứ chỉ nói rằng wait_i2c() làm việc với write_i2c() mà không làm việc với read_i2c() thì tôi bó tay. Vì những hàm đó là do bạn viết ra.

Thân,

scentoflove
20-08-2007, 05:23 PM
Code em viết trong file .h. Dựa vào TUT của anh bỏ đi một số phần kiểm tra cờ.

han_nang_008
30-11-2008, 07:42 PM
bác nào giúp em với, em viết chương trình gửi kí tự lên PC, và từ PC gửi xuống 30F4011, nhưng đều ra các kí tự là, %!@&....

code nhận dữ liệu từ PC

#include "p30f4011.h"
#include "uart.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//Chuong trinh cau hinh UART
//------------------------------------------------------------------------------
void Uart_Setup(void)
{
unsigned int baudvalue,U2MODEvalue,U2STAvalue;
CloseUART2();
ConfigIntUART2( UART_RX_INT_EN & UART_RX_INT_PR6 &
UART_TX_INT_DIS & UART_TX_INT_PR1 ) ;

baudvalue = (((7370000/9600)/16)-1); //baud=9600 bps ==> nhaapj vaof baudvalue = (((7370000/9600)/16)-1) voi Fcy = 7.37 Mhz,

U2MODEvalue = UART_EN & UART_IDLE_STOP & UART_RX_TX &
UART_DIS_WAKE & UART_DIS_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT &
UART_1STOPBIT;

U2STAvalue = UART_INT_TX &
UART_TX_PIN_NORMAL &
UART_TX_ENABLE &
UART_INT_RX_CHAR &
UART_ADR_DETECT_DIS &
UART_RX_OVERRUN_CLEAR;
OpenUART2(U2MODEvalue, U2STAvalue, baudvalue);
}

//========================== UART1 Interrupt Sub-Routine =====================//
void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
_U1RXIF = 0; //Xoa co ngat
lcd_putstr(ReadUART2()); //xuat chuoi ra LCD

}



//Chuong trinh chinh
//------------------------------------------------------------------------------
void main()
{ ADPCFG = 0xFFBF; //Cac chan khac la digital, chan AN0/RB0 la analog
_TRISE3 = 0;
Uart_Setup();
Init_PORTS_LCD(); //Khoi tao cac cong I/O

Init_LCD(); //Khoi tao LCD
lcd_putstr("TOC DO =");


while (1)
{
_LATE3=1;
Delay_ms(250); //Vong lap chinh
_LATE3=0;
Delay_ms(250);
}
}


code gủi dữ liệu lên PC

#include "p30f4011.h"

_FOSC(CSW_FSCM_OFF & FRC_PLL4); //Clock = 32 MHz
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

//Cac prototype cho cac chuong trinh con
void Init_TMR1(void);
void Init_UART2_Module(void);

//Bang hang so trong ROM

unsigned char Chuoi1[] = "Xin chao!";

//Cac bien toan cuc
unsigned char flag, idx;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
Init_TMR1(); //Khoi tao Timer 1
Init_UART2_Module(); //Khoi tao module UART1
flag = 0; //Xoa co bao het thoi gian cho
while (1) {
if (flag) { //Cho den khi het thoi gian cho
idx = 0;
while (Chuoi1[idx]) { //Neu chua het chuoi thi
U2TXREG = Chuoi1[idx++]; //Xuat tiep 1 ky tu
while (!U2STAbits.TRMT); //Cho den khi truyen xong ky tu
};
flag = 0;
};
};
}

//Chuong trinh con khoi tao module UART1
void Init_UART2_Module(void) {
U2MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
U2STA = 0x0400; //bit10=UTXEN
U2BRG = (((7370000/9600)/16)-1); //38400 bps @ Fcy = 8 MHz
}

//Chuong trinh con khoi tao Timer 1, tran sau moi 1 giay o muc xung 8 Mips
void Init_TMR1(void) {
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = 0x7A12; //Nguong tran la 1 giay tuong ung voi clock = 32 MHz
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}

//Chuong trinh xu ly ngat Timer 1
void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
flag = 1; //Bat co cho phep xuat chuoi ky tu
}



code viết bằng VB chung cho cả gửi và nhận

Private Sub Form_Load()


With MSComm1
.Settings = "9600,N,8,1"
.CommPort = 1
.RThreshold = 1
.SThreshold = 0
.InputMode = comInputModeText
.InputLen = 0
.Handshaking = comNone
.InBufferSize = 1024
.OutBufferSize = 1024
.PortOpen = True
End With
End Sub


Private Sub Form_Unload(Cancel As Integer)
' Dong cong
MSComm1.PortOpen = False
End Sub

Private Sub Command1_Click()
MSComm1.Output = Text1.Text
End Sub
Private Sub MSComm1_OnComm()
If (MSComm1.CommEvent = comEvReceive) Then
Text2.Text = Text2.Text + MSComm1.Input
End If
End Sub

namqn
30-11-2008, 09:23 PM
bác nào giúp em với, em viết chương trình gửi kí tự lên PC, và từ PC gửi xuống 30F4011, nhưng đều ra các kí tự là, %!@&....

...
Có vẻ như baudrate hai phía không giống nhau.

Thân,

han_nang_008
30-11-2008, 10:19 PM
Có vẻ như baudrate hai phía không giống nhau.

Thân,

Anh namqn ơi, trong code em đã set cả 2 baudrate đều là 9600 mà anh, anh xem hộ em với

namqn
30-11-2008, 10:28 PM
Anh namqn ơi, trong code em đã set cả 2 baudrate đều là 9600 mà anh, anh xem hộ em với
Bạn dùng FRC của dsPIC30F4011, và giả thiết nó là 7.37 MHz, nhưng lấy gì đảm bảo tần số của dsPIC30F4011 của bạn đúng bằng bao nhiêu đó?

Hơn nữa, để con số tính toán cho baudvalue được tròn trịa thì nên dùng 7372800 thay vì 7370000 trong công thức. Bạn thử lại xem.

Thân,

han_nang_008
30-11-2008, 11:02 PM
Bạn dùng FRC của dsPIC30F4011, và giả thiết nó là 7.37 MHz, nhưng lấy gì đảm bảo tần số của dsPIC30F4011 của bạn đúng bằng bao nhiêu đó?

Hơn nữa, để con số tính toán cho baudvalue được tròn trịa thì nên dùng 7372800 thay vì 7370000 trong công thức. Bạn thử lại xem.

Thân,

em thử lại 7372800 cũng ko dc bac ah

namqn
01-12-2008, 01:03 AM
em thử lại 7372800 cũng ko dc bac ah
Bây giờ bạn thử lại với một chương trình rất đơn giản, chỉ dùng PIC gửi chuỗi ký tự lên PC, và trên PC dùng một chương trình tiện ích nào đó như HyperTerminal để nhận.

Thân,

han_nang_008
15-12-2008, 02:47 PM
trong ví dụ 5.2 của bác đoặn thế này

while (1) {
if (flag) { //Neu co ket qua moi thi xuat ket qua
idx = (ADCValue >> 8); //Nibble cao nhat (chi co 2 bit)
U1TXREG = HexTable[idx]; //Chuyen thanh ky tu tuong ung
while (!U1STAbits.TRMT); //Cho den khi truyen xong ky tu
idx = ((ADCValue >> 4) & 0x000F); //Nibble thu hai
U1TXREG = HexTable[idx]; //Chuyen thanh ky tu tuong ung
while (!U1STAbits.TRMT); //Cho den khi truyen xong ky tu
idx = (ADCValue & 0x000F); //Nibble thap nhat
U1TXREG = HexTable[idx]; //Chuyen thanh ky tu tuong ung
while (!U1STAbits.TRMT); //Cho den khi truyen xong ky tu
U1TXREG = 0x0A; //Cap ky tu CR, LF
while (!U1STAbits.TRMT); //Cho den khi truyen xong ky tu
U1TXREG = 0x0D;
flag = 0; //Xoa co bao hieu co ket qua moi
};


em viết lại thành hàm chuyển số sang chuỗi như này

//khai báo bien toan cuc
char chuoi[4];

unsigned char HexTable[] = "0123456789";
void so_to_chuoi(int so)
{

int idx;
int temp;
temp=so;
idx = ((temp >> 12) & 0x000F); //Nibble cao nhat (chi co 2 bit)
chuoi[0] = HexTable[idx];

idx = ((temp >> 8) & 0x000F); //Nibble cao nhat (chi co 2 bit)
chuoi[1] = HexTable[idx];

idx = ((temp >> 4) & 0x000F); //Nibble cao nhat (chi co 2 bit)
chuoi[2] = HexTable[idx]; //Chuyen thanh ky tu tuong ung

idx = (temp & 0x000F); //Nibble thu hai
chuoi[3]= HexTable[idx]; //Chuyen thanh ky tu tuong ung


}


trong hàm main em viết đoặn
so_to_chuoi(5893);
putsUART2((unsigned int*)chuoi);

rồi truyền lên PC thì thì ko thẻ nhận đúng số 5839, mà nhạn sang số khác,
đổi sang so_to_chuoi(so bat ki); thì cũng ko nhận đúng
nếu trong hàm so_to_chuoi(); em gán idx là các số cố định thì nhận dc chính xác, em suy ra là phần tách số có vấn đề, nhung em thử cackeeiur đều ko dc.
Bác xem hộ em với

bien_van_khat
15-12-2008, 04:07 PM
Giải thuật trong hàm so_to_chuoi của bạn thực chất là đổi 1 số sang dạng chuỗi nhưng ở hệ cơ số 16. Bảng HexTable của bạn lại chỉ có các ký tự từ 0-9, thiếu các ký tự A-F.

VD số 5893 của bạn, khi qua hàm sẽ ra chuỗi '1705', ngoài ra chuỗi này ko được kết thúc bởi ký tự NULL, do đó hàm putsUART2 sẽ ko hoạt động đúng khi bạn truyền tham số là chuỗi này.

han_nang_008
15-12-2008, 07:26 PM
mình chỉ chuyển sô gồm những chữ số ko có A- F, nên mình ko têm vào hextable,
nhưng mình có đổi lại thành HexTable[] = "0123456789ABCDEF" thì kết quả vẫn thế, bạn dựa vào đầu mà bạn biết dc truyền 5893 mà lại nhận dc 1705 thế

namqn
15-12-2008, 07:41 PM
mình đã đổi lại thành HexTable[] = "0123456789ABCDEF" nung kết quả vẫn thế, bạn dựa vào đầu mà bạn biết dc truyền 5893 mà lại nhận dc 1705 thế
5893 = 0x1705. Code của tôi chuyển từng nibble (4 bit) của một số hexadecimal thành một ký tự tương ứng. Bạn áp dụng khi chưa hiểu rõ.

Muốn chuyển một số thập phân thành chuỗi biểu diễn giá trị của nó thì bạn phải dùng cách tương tự như hàm itoa(), có sẵn trong thư viện của một số trình biên dịch. Với MPLAB C Compiler for dsPIC thì bạn phải tự làm, cũng không khó lắm. PIClist (www.piclist.com) có các đoạn code C mẫu cho việc chuyển đổi số nguyên sang ASCII (không may là server hiện thời của piclist chạy khá chậm).

Code cho mục đích của bạn (chuyển số nguyên 16-bit sang chữ số thập phân dạng ASCII) có ở đây:
http://www.piclist.com/techref/language/ccpp/convertbase.htm

Code trên PIClist xuất xứ từ đây (bài viết của Associate Professor Douglas W. Jones):
http://www.cs.uiowa.edu/~jones/bcd/decimal.html


Thân,

han_nang_008
15-12-2008, 08:38 PM
bác namqn có thể cop đoặn code đấy cho em được ko ah, code chuyển số thập phân sang chuỗi, chuyển số nguyên 16 bit sang chuỗi với,
web của bác cho em ko vào được, phiền bác quá.
bác cho em hỏi thêm hàm làm tròn 1 số tron C30 là j hả bác, ví dụ làm tròn số 13,6 thành 14
Thank bác nhiều

namqn
15-12-2008, 11:37 PM
bác namqn có thể cop đoặn code đấy cho em được ko ah, code chuyển số thập phân sang chuỗi, chuyển số nguyên 16 bit sang chuỗi với,
web của bác cho em ko vào được, phiền bác quá.
bác cho em hỏi thêm hàm làm tròn 1 số tron C30 là j hả bác, ví dụ làm tròn số 13,6 thành 14
Thank bác nhiều
Code chuyển số thập phân 16-bit sang chuỗi ASCII (d4..d0):
void putdec( short int n )
{
unsigned char d4, d3, d2, d1, d0, q;

if (n < 0) {
putchar( '-' );
n = -n;
}

d1 = (n>>4) & 0xF;
d2 = (n>>8) & 0xF;
d3 = (n>>12) & 0xF;

d0 = 6*(d3 + d2 + d1) + (n & 0xF);
q = (d0 * 0xCD) >> 11;
d0 = d0 - 10*q;

d1 = q + 9*d3 + 5*d2 + d1;
q = (d1 * 0xCD) >> 11;
d1 = d1 - 10*q;

d2 = q + 2*d2;
q = (d2 * 0x1A) >> 8;
d2 = d2 - 10*q;

d3 = q + 4*d3;
d4 = (d3 * 0x1A) >> 8;
d3 = d3 - 10*d4;

putchar( d4 + '0' );
putchar( d3 + '0' );
putchar( d2 + '0' );
putchar( d1 + '0' );
putchar( d0 + '0' );
}


MPLAB C Compiler for dsPIC có các hàm làm tròn số như sau: floor()-làm tròn xuống (tức là chỉ lấy phần nguyên, 13.9 => 13), và ceil()-làm tròn lên (tức là lấy số nguyên lớn hơn gần nhất, 13.4 => 14). Bạn nhớ dùng #include <math.h> ở đầu tập tin mã nguồn.

Thân,

ham_hoc_hoi
14-01-2009, 11:43 PM
bác namqn cho em hỏi vấn đề này. trên VB6 em viết cho 1 nút ấn đơn giản là khi ân nút thì truyền 1 lúc 12 byte ví dụ là chữ "XIN CHAO BAN" với 12 lênh MSComm1.Output = các kí tự tương ứng.
ở vdk em cấu hình UART như sau

U2MODE = 0x8000; //Main I/O, 8-bit, no parity, 1 stop bit
U2STA = 0x0400; //bit10=UTXEN, ngắt khi nhận 1 kí tự
U2BRG = 32; //9600 bps @ Fcy = 5 MHz

trong hàm ngắt em viết vi dụ như sau

void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
_U2RXIF = 0;
m++;
if (m==5)
{ putstr(U2RXREG);}
}

thi đoặn này nhẽ ra phải hiện chữ C, nhưng lại ko hiện chữ j
nếu em thay if(m==1) thì hiện ra đúng chữ X, nhung thay if(m==2) vẫn hiện ra chứ X, còn thay if(m==3 hoặc 4 hoặc 5.....) thì ko hiện ra chữ j cả
em thay thành đoặn code sau

void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
_U2RXIF = 0;
m++;

dislayLCD(m);
}

để đếm số lần ngắt thì nó hiển thị m=2, nghĩa là em truyền 1 lúc 12 byte thì chỉ xảy ra 2 lần ngắt, cho nên ở đoặn trên với if(m== sô lớn hơn 2) là ko hiển thị đuọc. Em đã đặt chế độ ngắt khi nhận dc 1 byte, vậy trong tr hợp này m phải bằng 12 chứ bác, tốc đọ truyền của vdk và PC đều là 9600.
Với đoặn trên thì từ trên PC em viết lại là ấn nút thì chỉ truyền 1 byte thôi thì ở dưới số lần ngắt có tăng lên, nhưng m chỉ bằng đến 4 là ko tăng nữa, mặc dù vẫn ấn truyền. Tr hợp này thì như nào hả bác. Mong bác giải thích cho em và chỉ em cách để làm sao mà mình truyền trên PC 1 lúc nhiều byte thì vdk nhận từng byte sẽ ngắt đúng hả bác

namqn
15-01-2009, 02:24 AM
Khi có ngắt nhận ký tự ở dsPIC, bạn chỉ tăng biến đếm chứ không lấy ký tự ra khỏi bộ đệm của UART. Bạn nên tạo một bộ đệm ở dsPIC, khi có ký tự là lấy ngay ra khỏi bộ đệm (giả sử bộ đệm là buff[], trong đoạn code xử lý ngắt bạn thực hiện buff[i] = U2RXREG, i cần được khởi tạo trước đó).

Nên xóa cờ ngắt sau khi đã phục vụ xong ngắt, thay vì ngay đầu code xử lý ngắt. Cách đơn giản để phản hồi về PC của bạn là khi vào code xử lý ngắt, bạn đọc được ký tự nào thì gửi ngược ký tự đó về PC. Ví dụ, U2TXREG = buff[i].

Bộ đệm của UART trong dsPIC chỉ chứa được 4 ký tự, do đó bạn chỉ nhận được 4 ký tự đầu tiên (các ký tự sau đó sẽ bị dsPIC bỏ qua, vì lý do tràn bộ đệm, mời bạn xem lại các tài liệu đã được tôi đề cập trong tutorial). Cũng mời bạn đọc lại tutorial của tôi.

Những gì tôi vừa nêu trên đã được đề cập trong tutorial.

Thân,

ham_hoc_hoi
15-01-2009, 06:03 PM
Khi có ngắt nhận ký tự ở dsPIC, bạn chỉ tăng biến đếm chứ không lấy ký tự ra khỏi bộ đệm của UART. Bạn nên tạo một bộ đệm ở dsPIC, khi có ký tự là lấy ngay ra khỏi bộ đệm (giả sử bộ đệm là buff[], trong đoạn code xử lý ngắt bạn thực hiện buff[i] = U2RXREG, i cần được khởi tạo trước đó).

Nên xóa cờ ngắt sau khi đã phục vụ xong ngắt, thay vì ngay đầu code xử lý ngắt. Cách đơn giản để phản hồi về PC của bạn là khi vào code xử lý ngắt, bạn đọc được ký tự nào thì gửi ngược ký tự đó về PC. Ví dụ, U2TXREG = buff[i].

Bộ đệm của UART trong dsPIC chỉ chứa được 4 ký tự, do đó bạn chỉ nhận được 4 ký tự đầu tiên (các ký tự sau đó sẽ bị dsPIC bỏ qua, vì lý do tràn bộ đệm, mời bạn xem lại các tài liệu đã được tôi đề cập trong tutorial). Cũng mời bạn đọc lại tutorial của tôi.

Những gì tôi vừa nêu trên đã được đề cập trong tutorial.

Thân,
thế để mình nhận được nhiều hơn 4 kí tự thì mình phải cóa bọ đêm đi hả bac, hay làm như thế nào ah.
Còn khi em tr 1 lúc 12 byte thì sao chỉ xảy ra có 2 lần ngắt ah

namqn
15-01-2009, 06:26 PM
thế để mình nhận được nhiều hơn 4 kí tự thì mình phải cóa bọ đêm đi hả bac, hay làm như thế nào ah.
Còn khi em tr 1 lúc 12 byte thì sao chỉ xảy ra có 2 lần ngắt ah
Bạn đọc kỹ lại bài viết của tôi. Tôi đã nói là đọc từ bộ đệm ra khi nhận được ký tự (để giải phóng bộ đệm cho việc nhận ký tự kế tiếp).

Khi bạn truyền ồ ạt 12 ký tự thì có thể giữa các ký tự có thời gian nghỉ không đủ lớn (một bạn thành viên trên diễn đàn này cũng đã gặp điều đó, tôi có đề nghị thêm vào một khoảng delay nhỏ giữa các ký tự ở phía PC thì đã giải quyết được). Ngoài phần phục vụ ngắt UART thì dsPIC còn có thể phải phục vụ các ngắt khác ở mức ưu tiên cao hơn, điều này bạn chưa cho biết.

Thân,

conglong
15-03-2009, 09:59 AM
Thầy Nam cho em hỏi : em muốn giao tiêp PC vơi dsPIC30f2010 , bằng cách dùng PC gửi kí tự xuống dsPIC sau đó dsPIC hiện thị những kí tự vừ nhận lên màn hình LCD và gửi lại cho PC , project em làm là dựa trên code của thầy (cả TUTO LCD và UART), nhưng không hiểu sao nó không chạy, nếu không có hiện thị lên LCD thì chạy bình thường(em dùng hyper terminal) . Module LCD của em nó cũng chạy rồi . Nhưng cứ "nối" 2 module này lại là không chạy !
Em cảm ơn Thầy !
Trân trọng !

conglong
15-03-2009, 10:13 AM
Thầy Nam cho em hỏi câu nữa liên quan tới C30 là: giả sử em đã có 2 project LCD và UART , mà trong project UART em muốn hiện thị LCD , vậy em có thể dung thêm lệnh preprocessor ở đầu project UART là
"#include LCD.c"
Để lấy hàm hiện thị
"LCD_puttring()"
trong LCD. c được không thầy ,
Em cảm ơn !
Trân trọng !.

namqn
15-03-2009, 08:19 PM
Thầy Nam cho em hỏi : em muốn giao tiêp PC vơi dsPIC30f2010 , bằng cách dùng PC gửi kí tự xuống dsPIC sau đó dsPIC hiện thị những kí tự vừ nhận lên màn hình LCD và gửi lại cho PC , project em làm là dựa trên code của thầy (cả TUTO LCD và UART), nhưng không hiểu sao nó không chạy, nếu không có hiện thị lên LCD thì chạy bình thường(em dùng hyper terminal) . Module LCD của em nó cũng chạy rồi . Nhưng cứ "nối" 2 module này lại là không chạy !
Em cảm ơn Thầy !
Trân trọng !
Như thế nào là không chạy? Hoàn toàn không chạy hay chạy sai ở chỗ nào đó?

Tốc độ gửi dữ liệu của bạn ra sao? Mỗi giây một giá trị từ PC hay thế nào?

Hàm lcd_putstr() của bạn nhận đối số là một chuỗi ký tự, nhưng bạn lại gọi hàm với đối số là temp (có kiểu unsigned short). Lần trước tôi đã hướng dẫn bạn dùng hàm sprintf() để chuyển giá trị số thành một chuỗi ký tự trước khi xuất ra LCD rồi mà.

Thân,

namqn
15-03-2009, 08:23 PM
Thầy Nam cho em hỏi câu nữa liên quan tới C30 là: giả sử em đã có 2 project LCD và UART , mà trong project UART em muốn hiện thị LCD , vậy em có thể dung thêm lệnh preprocessor ở đầu project UART là
"#include LCD.c"
Để lấy hàm hiện thị
"LCD_puttring()"
trong LCD. c được không thầy ,
Em cảm ơn !
Trân trọng !.
Bạn có thể kết hợp nhiều tập tin mã nguồn vào một project, những hàm nào nằm ở module biên dịch (tập tin mã nguồn) khác thì cần được khai báo trước khi sử dụng (thường dùng tập tin header để gộp các khai báo biến, prototype của hàm, ...).

Nếu bạn dùng "#include LCD.c" thì trình biên dịch chỉ đơn giản bê nguyên nội dung của "LCD.c" đặt vào tập tin mã nguồn hiện tại của bạn thôi. Tôi không cho đây là cách làm hay. Không rõ bạn có được học về lập trình C trong chương trình đại học hay không?

Thân,

conglong
16-03-2009, 05:15 PM
Như thế nào là không chạy? Hoàn toàn không chạy hay chạy sai ở chỗ nào đó?

Tốc độ gửi dữ liệu của bạn ra sao? Mỗi giây một giá trị từ PC hay thế nào?

Hàm lcd_putstr() của bạn nhận đối số là một chuỗi ký tự, nhưng bạn lại gọi hàm với đối số là temp (có kiểu unsigned short). Lần trước tôi đã hướng dẫn bạn dùng hàm sprintf() để chuyển giá trị số thành một chuỗi ký tự trước khi xuất ra LCD rồi mà.

Thân,
em có sửa lại định nghĩa của biến temp là

char temp[1];

mà nó vẫn không chạy ; Không chạy ở đây là : Hyper terminal không detect được tốc độ truyền và định dạng truyền, em truyền 1 kí tự từ bàn phím , sau 2s hoặc lâu hơn em nhấn bàn phím 1 lần mà không thấy kết quả.
em cảm ơn thấy !
Trân trọng !.

conglong
16-03-2009, 05:21 PM
Bạn có thể kết hợp nhiều tập tin mã nguồn vào một project, những hàm nào nằm ở module biên dịch (tập tin mã nguồn) khác thì cần được khai báo trước khi sử dụng (thường dùng tập tin header để gộp các khai báo biến, prototype của hàm, ...).

Nếu bạn dùng "#include LCD.c" thì trình biên dịch chỉ đơn giản bê nguyên nội dung của "LCD.c" đặt vào tập tin mã nguồn hiện tại của bạn thôi. Tôi không cho đây là cách làm hay. Không rõ bạn có được học về lập trình C trong chương trình đại học hay không?

Thân,
ý của thầy là :
tạo một tập tin header nữa (ex: UartHeader.h), trong tập tin này có
#Include LCD.c;
Và trong file mã nguồn (UART.c) em dung lệnh
#include UartHeader.h
???
Em mới học VB còn C thì em đang học thầy ạ, nên có nhiều câu hỏi hơi "NGỖ" mong thầy thông cảm.
Em cảm ơn!
Trân trọng !.

namqn
16-03-2009, 06:43 PM
em có sửa lại định nghĩa của biến temp là

char temp[1];

mà nó vẫn không chạy ; Không chạy ở đây là : Hyper terminal không detect được tốc độ truyền và định dạng truyền, em truyền 1 kí tự từ bàn phím , sau 2s hoặc lâu hơn em nhấn bàn phím 1 lần mà không thấy kết quả.
em cảm ơn thấy !
Trân trọng !.
PIC không phát dữ liệu gì cả thì làm sao HyperTerminal detect được tốc độ truyền. Bạn phải tự thiết lập tốc độ truyền của HyperTerminal cho phù hợp với tốc độ đã thiết lập của PIC.

Nếu bạn định nghĩa biến temp như trên thì temp tương thích với hàm lcd_putstr(), nhưng khi bạn dùng lệnh gán giá trị của U1RXREG vào temp thì kết quả sẽ khác với sự mong đợi của bạn (vì temp sẽ giống như một con trỏ, và giá trị của nó sẽ bị thay đổi, chứ không phải là nội dung của ô nhớ mà nó trỏ tới sẽ bị thay đổi).

Thân,

namqn
16-03-2009, 06:47 PM
ý của thầy là :
tạo một tập tin header nữa (ex: UartHeader.h), trong tập tin này có
#Include LCD.c;
Và trong file mã nguồn (UART.c) em dung lệnh
#include UartHeader.h
???
Em mới học VB còn C thì em đang học thầy ạ, nên có nhiều câu hỏi hơi "NGỖ" mong thầy thông cảm.
Em cảm ơn!
Trân trọng !.
Ý của tôi là trong tập tin .h, bạn sẽ khai báo các hàm của module mã nguồn khác theo cú pháp của C30, và include tập tin đó vào module hiện thời của bạn. Ý của tôi không phải như trên.

Nếu bạn đang học C, bạn có thể đem những vấn đề này ra hỏi thầy dạy của bạn. Nếu bạn vẫn không nắm được vấn đề, đề nghị bạn tìm đọc một tài liệu hướng dẫn lập trình căn bản cho C.

Vì đây là diễn đàn về PIC/dsPIC, tôi chỉ hướng dẫn những vấn đề liên quan đến PIC/dsPIC (trong tầm hiểu biết của tôi), và tôi không có ý định hướng dẫn sử dụng các ngôn ngữ lập trình cấp cao.

Thân,

conglong
16-03-2009, 09:36 PM
PIC không phát dữ liệu gì cả thì làm sao HyperTerminal detect được tốc độ truyền. Bạn phải tự thiết lập tốc độ truyền của HyperTerminal cho phù hợp với tốc độ đã thiết lập của PIC.

Thân,
dạ vâng, nó chạy rồi thầy ạ tại con RS 232 bị lỏng chân cắm , nhưng vẫn chưa như ý muốn , chắc là tại ở biến :temp; cái nầy em giải quyết được với hàm Sprintf() như thầy chỉ hôm trước.Trong sơ đồ kết nối thầy dùng U1ATX và U1ARX pin mà tại sao trong hàm
void Init_UART1_Module(void)
Thầy lại config thanh ghi U1MODE là
U1MODE = 0x8000;
Em nghĩ phải là
U1MODE = 0x8400; chứ thầy?
Em cảm ơn!
Trân trọng!.

conglong
16-03-2009, 09:59 PM
Trong TUTO về I2C (vidu4.3) thầy có dùng các lệnh sau em không hiểu lắm: (chố em không hiểu em có comment ở ngay sau lệnh) mong thầy nói rõ cho em với :


Wait_I2C(); //trong hàm này thầy dùng cờ ngắt là _MI2CIF vậy sao thầy
//không set bit enable _MI2CIE trong hàm void Init_PORTS(void)?

Send_I2C(0xD0);//tại sao đây là dịa chỉ của ds1307 số khác được khôngthầy ?



Send_I2C(0x67);
// trước khi ghi vào REG 02 của RTM thì phải gửi điạ //chỉ chứ (giống như các lệnh thao tác //trên //REG01?? con số hex 67 có nghĩa gì ?)

Send_I2C(0x01);
//Xuat số con số 01 nầy là chỉ Thứ 2 của tuần phài //không ?

Send_I2C(0x25); //Xuat noi dung cua thanh ghi 0x04 (dem ngay)
Send_I2C(0x08); //Xuat noi dung cua thanh ghi 0x05 (dem thang)
// hai số hex 25 và 08 có nghĩa gì?

em cảm ơn !
Trân trọng !.

namqn
16-03-2009, 11:18 PM
dạ vâng, nó chạy rồi thầy ạ tại con RS 232 bị lỏng chân cắm , nhưng vẫn chưa như ý muốn , chắc là tại ở biến :temp; cái nầy em giải quyết được với hàm Sprintf() như thầy chỉ hôm trước.Trong sơ đồ kết nối thầy dùng U1ATX và U1ARX pin mà tại sao trong hàm
void Init_UART1_Module(void)
Thầy lại config thanh ghi U1MODE là
U1MODE = 0x8000;
Em nghĩ phải là
U1MODE = 0x8400; chứ thầy?
Em cảm ơn!
Trân trọng!.
Nếu bạn đọc trang 2 của tutorial, sẽ thấy tôi ghi là ví dụ 4-1 và 4-2 sẽ dùng main I/O của UART, và sẽ không thể hiện trong sơ đồ. Do vậy, sơ đồ mà tôi đã thể hiện trong tutorial là cho ví dụ 4-3 và 4-4 (bạn nên đọc kỹ lại), trong đó, chỉ có ví dụ 4-4 là có dùng UART, và tôi đã thiết lập U1MODE là 0x8400 trong ví dụ 4-4.

Thân,

namqn
16-03-2009, 11:24 PM
Trong TUTO về I2C (vidu4.3) thầy có dùng các lệnh sau em không hiểu lắm: (chố em không hiểu em có comment ở ngay sau lệnh) mong thầy nói rõ cho em với :


Wait_I2C(); //trong hàm này thầy dùng cờ ngắt là _MI2CIF vậy sao thầy
//không set bit enable _MI2CIE trong hàm void Init_PORTS(void)?

Send_I2C(0xD0);//tại sao đây là dịa chỉ của ds1307 số khác được khôngthầy ?



Send_I2C(0x67);
// trước khi ghi vào REG 02 của RTM thì phải gửi điạ //chỉ chứ (giống như các lệnh thao tác //trên //REG01?? con số hex 67 có nghĩa gì ?)

Send_I2C(0x01);
//Xuat số con số 01 nầy là chỉ Thứ 2 của tuần phài //không ?

Send_I2C(0x25); //Xuat noi dung cua thanh ghi 0x04 (dem ngay)
Send_I2C(0x08); //Xuat noi dung cua thanh ghi 0x05 (dem thang)
// hai số hex 25 và 08 có nghĩa gì?

em cảm ơn !
Trân trọng !.
Việc dùng cờ ngắt _MI2CIF không liên quan đến việc ngắt MI2C có được cho phép hay không. Cờ ngắt _MI2CIF sẽ thay đổi trạng thái theo trạng thái của bộ đệm dữ liệu, chứ không phụ thuộc vào việc ngắt MI2C có được enable hay không.

Địa chỉ 0xD0 của DS1307 là do nhà sản xuất vi mạch DS1307 quy định, nếu không dùng đúng giá trị này thì DS1307 sẽ không đáp ứng với các yêu cầu đã được gửi ra bus I2C.

Những vấn đề liên quan đến các câu hỏi còn lại của bạn đều được mô tả trong datasheet của DS1307, đề nghị bạn đọc nó. Những thông tin điều khiển gửi đến một vi mạch ngoài PIC cần tuân thủ những yêu cầu đã đề ra trong datasheet của vi mạch đó.

Thân,

KENJY
03-04-2009, 06:52 PM
Tutorial 4 cho dsPIC, viết bằng ASM30 lẫn C30, giới thiệu các module UART và I2C (chế độ master). Các ví dụ về module UART thực hiện giao tiếp với máy tính. Các ví dụ về module I2C thực hiện giao tiếp với vi mạch thời gian thực DS1307.

Tập tin "Vidu4.zip" gồm các tập tin nguồn hợp ngữ và .hex. Tập tin "Vidu4C30.zip" gồm các tập tin nguồn C và .hex.

Thân,

Thầy Nam có thể cho em sơ đồ mô phỏng trên Proteus cua tutorial này không?

namqn
03-04-2009, 08:52 PM
Thầy Nam có thể cho em sơ đồ mô phỏng trên Proteus cua tutorial này không?
Như đã trả lời bạn qua tin nhắn, tôi không mô phỏng các tutorial, do đó các sơ đồ của tôi không dùng được cho việc mô phỏng.

Thân,

Hiepnv101
11-05-2009, 06:16 PM
void Init_TMR1(void)
{
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = 0x7A12; //Nguong tran la 1 giay tuong ung voi clock = 32 MHz
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}
Theo em nghĩ là bộ đếm sẽ đếm giá trị từ PR1 đến giá trị 65535, khi vượt qua giá trị này sẽ tạo ngắt Timer1. Anh Nam đặt giá trị 7A12 vào PR1 liệu đã tạo ra ngắt đúng 1giây không ?

conglong
11-05-2009, 07:35 PM
void Init_TMR1(void)
{
TMR1 = 0; //Xoa so dem trong TMR1
PR1 = 0x7A12; //Nguong tran la 1 giay tuong ung voi clock = 32 MHz
_T1IF = 0; //Xoa co ngat cua Timer 1
T1CON = 0x8030; //Dung fcy lam clock, prescale = 1:256
_T1IE = 1; //Cho phep ngat khi Timer 1 tran
}
Theo em nghĩ là bộ đếm sẽ đếm giá trị từ PR1 đến giá trị 65535, khi vượt qua giá trị này sẽ tạo ngắt Timer1. Anh Nam đặt giá trị 7A12 vào PR1 liệu đã tạo ra ngắt đúng 1giây không ?

Không phải đâu ban, Timer sẽ đếm từ 0 cho tới giá trị PRx, giá tri của bộ đếm Timer sẽ lưu vào TMRx ,(x ở đây là chỉ số timer x=1 ,2..) và khi TMRx = PRx thì ngắt Timer sẽ được gọi (nếu bạn set bit _TxIE ), đồng thời reset giá trị trong thanh ghi TMRx về zero,và lặp lại công việc như trên mãi.
Trân trọng!
à mà dạo này Picvietnam thấy sa sút qua thầy Nam ơi !

Hiepnv101
15-05-2009, 05:54 PM
Anh Nam cho em hỏi. Em khai báo _FBORPOR(PBOR_OFF & MCLR_EN); thì truyền lên PC rất nhiễu. Nhưng khi khai báo _FBORPOR(PBOR_OFF & MCLR_DIS); thì lại truyền rất chuẩn. Anh có thể nêu qua 2 khai báo này được không ạ?

Thanks,

silvadk2
21-05-2009, 10:10 AM
Em có 1 vấn đề về phần cứng. Em làm mạch đo nhiệt độ, hiển thị lên LCD và gửi lên máy tính. Phần đo nhiệt độ và hiển thì lên LCD thì ok, nhưng cứ khi em cắm COM vào mt thì mạch lại ko làm việc nữa, chip thì nóng lên. Em thử ktra các chân của Max232 và com thì thấy bình thường, thậm chí, cắm com nhưng ko cắm lên máy tính thì mạch cũng ko sao, vẫn bình thường. Em thử cắm sang nhiều máy tính khác thì nó cũng ko chạy, theo mọi người thì lỗi ở đâu nhỉ ?

tungnh
21-05-2009, 12:03 PM
Em có 1 vấn đề về phần cứng. Em làm mạch đo nhiệt độ, hiển thị lên LCD và gửi lên máy tính. Phần đo nhiệt độ và hiển thì lên LCD thì ok, nhưng cứ khi em cắm COM vào mt thì mạch lại ko làm việc nữa, chip thì nóng lên. Em thử ktra các chân của Max232 và com thì thấy bình thường, thậm chí, cắm com nhưng ko cắm lên máy tính thì mạch cũng ko sao, vẫn bình thường. Em thử cắm sang nhiều máy tính khác thì nó cũng ko chạy, theo mọi người thì lỗi ở đâu nhỉ ?

Bạn thử thay dây cổng COM khác xem thế nào

silvadk2
21-05-2009, 01:12 PM
dây đó em chạy với 1 mạch khác, nó ok bác ạ! mà có mỗi 1 dây, ngại đi mua quá. với lại mạch kia chạy ok thì chắc dây ko vấn đề

silvadk2
21-05-2009, 02:00 PM
Ô hô, em tìm ra lỗi rồi, do con vdk chết module uart, em thay con khác thì nó gửi ký tự rồi. Nhưng lạ 1 nỗi, cứ cắm com vào mt thì chip nóng ran. thế là thế nào nhỉ các bác. Néu cắm com mà ko cắm vào mt thì chip ko nóng, hic :(

namqn
21-05-2009, 10:45 PM
Anh Nam cho em hỏi. Em khai báo _FBORPOR(PBOR_OFF & MCLR_EN); thì truyền lên PC rất nhiễu. Nhưng khi khai báo _FBORPOR(PBOR_OFF & MCLR_DIS); thì lại truyền rất chuẩn. Anh có thể nêu qua 2 khai báo này được không ạ?

Thanks,
PBOR là viết tắt của Programmable Brown-Out Reset, tức là chức năng tự động reset khi nguồn suy giảm.

MCLR là viết tắt của Master Clear (Reset), tức là chức năng reset bộ xử lý khi chân MCLR được đặt ở trạng thái tích cực (mức logic '0').

Việc nhiễu khác nhau ở hai cấu hình của bạn thì vẫn chưa có đủ thông tin để góp ý. Bạn dùng sơ đồ nguyên lý như thế nào (chân MCLR của bạn được thiết kế ra sao, vì trong hai cấu hình thì chỉ có chức năng của chân MCLR là khác nhau)?

Thân,

conglong
07-09-2009, 01:42 PM
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về một số liên quan tới UART của dsPIC.
Em đang làm đồ án môn học liên quan tới PID trên máy tính rồi truyền giá trị xuống cho dsPIC. Giá trị em muốn truyền là thông số cho PDC1 và PDC2 (hai thanh ghi thiết lập duty_cycle trong module PWM )cho 2 bánh của robot. hai giá trị em gửi xuống cho dsPIC có tầm từ 0 tới 1599. nên cho em hỏi là có cách nào truyền từ máy tính xuống mà 1 lúc truyền được 16 bit data không ?. em đang làm việc với VC++. em chỉ thấy 1 frame truyền được 8 bit data mà chưa thấy truyền 1 frame 16 bits data . Nếu không truyền được 16 bits data /frame thì bài toán vừa nêu em định làm như sau :
Với giá trị cho thanh ghi PDC1 : em truyền byte đầu (8 bits thấp) cho dsPIC , lưu giá trị này vào biến có tên là temp1 , sau đó truyền tiếp byte thứ 2 (8 bits cao) và lưu vào temp2 , sau đó thực hiện phép tính :
PDC1 = (temp2<<8) + temp1;
tương tự với giá trị truyền cho PDC2.
Nhưng em vẫn chưa biết cách thiết lập ngắt cho module UART khi nó nhận xong 4 byte (em muốn nhận xong 4 byte rồi ngắt). và lấy 4 byte vừa nhận ở những thanh ghi nào vì em chỉ thấy có 1 thanh ghi lưu giá trị mà dsPIC nhận thôi ah ?
Cảm ơn thầy và các anh chị nhiều .
Trân trọng !.

namqn
07-09-2009, 04:05 PM
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về một số liên quan tới UART của dsPIC.
Em đang làm đồ án môn học liên quan tới PID trên máy tính rồi truyền giá trị xuống cho dsPIC. Giá trị em muốn truyền là thông số cho PDC1 và PDC2 (hai thanh ghi thiết lập duty_cycle trong module PWM )cho 2 bánh của robot. hai giá trị em gửi xuống cho dsPIC có tầm từ 0 tới 1599. nên cho em hỏi là có cách nào truyền từ máy tính xuống mà 1 lúc truyền được 16 bit data không ?. em đang làm việc với VC++. em chỉ thấy 1 frame truyền được 8 bit data mà chưa thấy truyền 1 frame 16 bits data . Nếu không truyền được 16 bits data /frame thì bài toán vừa nêu em định làm như sau :
Với giá trị cho thanh ghi PDC1 : em truyền byte đầu (8 bits thấp) cho dsPIC , lưu giá trị này vào biến có tên là temp1 , sau đó truyền tiếp byte thứ 2 (8 bits cao) và lưu vào temp2 , sau đó thực hiện phép tính :
PDC1 = (temp2<<8) + temp1;
tương tự với giá trị truyền cho PDC2.
Nhưng em vẫn chưa biết cách thiết lập ngắt cho module UART khi nó nhận xong 4 byte (em muốn nhận xong 4 byte rồi ngắt). và lấy 4 byte vừa nhận ở những thanh ghi nào vì em chỉ thấy có 1 thanh ghi lưu giá trị mà dsPIC nhận thôi ah ?
Cảm ơn thầy và các anh chị nhiều .
Trân trọng !.
Bạn sẽ không thể truyền 16 bit dữ liệu liên tiếp. Bạn tách 16 bit dữ liệu thành 2 byte là ổn. Để thiết lập module UART tạo ngắt sau khi nhận được 4 byte, bạn đặt các bit URXISEL<1:0> trong thanh ghi U1STA bằng '11' (giả sử bạn đang dùng module UART1).

Để lấy các byte dữ liệu khi có ngắt, bạn liên tiếp đọc thanh ghi U1RXREG (giả sử bạn đang dùng module UART1). Vì các module UARTx sử dụng bộ đệm FIFO (First-In First-Out), nên các byte được nhận trước sẽ được đọc ra trước. Cụ thể, ví dụ từ máy tính bạn lần lượt gửi các giá trị a, b, c, và d đến dsPIC. Sau khi nhận được giá trị d, dsPIC sẽ tạo ra ngắt, và khi xử lý ngắt, nếu bạn liên tiếp đọc thanh ghi U1RXREG thì bạn sẽ lần lượt nhận được các giá trị a, b, c, và d.

Thân,

conglong
07-09-2009, 09:44 PM
Bạn sẽ không thể truyền 16 bit dữ liệu liên tiếp. Bạn tách 16 bit dữ liệu thành 2 byte là ổn. Để thiết lập module UART tạo ngắt sau khi nhận được 4 byte, bạn đặt các bit URXISEL<1:0> trong thanh ghi U1STA bằng '11' (giả sử bạn đang dùng module UART1).

Để lấy các byte dữ liệu khi có ngắt, bạn liên tiếp đọc thanh ghi U1RXREG (giả sử bạn đang dùng module UART1). Vì các module UARTx sử dụng bộ đệm FIFO (First-In First-Out), nên các byte được nhận trước sẽ được đọc ra trước. Cụ thể, ví dụ từ máy tính bạn lần lượt gửi các giá trị a, b, c, và d đến dsPIC. Sau khi nhận được giá trị d, dsPIC sẽ tạo ra ngắt, và khi xử lý ngắt, nếu bạn liên tiếp đọc thanh ghi U1RXREG thì bạn sẽ lần lượt nhận được các giá trị a, b, c, và d.

Thân,

ah, dạ em cảm ơn thầy nhiều !
Trân trọng !.

npbaoduy
30-10-2009, 09:50 PM
Em có đoạn code như sau, với ý tưởng là lưu một byte vô ROM (0x66) vào địa chỉ 0001, sau đó đọc lại byte đó và gởi ra cổng nối tiếp, nhưng em không đạt kết quả (không gởi ra cổng nối tiếp được gì)

int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
Init_I2C(); //Khoi tao module I2C
Init_UART1_Module();
Init_TMR1();
//Buoc 1, tao dieu kien START, cho hoat dong I2C hoan tat
_SEN = 1;
Wait_I2C(); //Cho hoat dong I2C hoan tat
//Buoc 2, xuat dia chi cua ROM voi thao tac ghi, cho va kiem tra ACK
Write_I2C(0xA0); //Xuat dia chi cua ROM, sap ghi vao ROM
Wait_I2C(); //Cho hoat dong I2C hoan tat
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi dung chuong trinh
//Buoc 3, xuat dia chi cua thanh ghi dich (target), cho va kiem tra ACK
Write_I2C(0x00); //Xuat dia chi cao
Wait_I2C(); //Cho hoat dong I2C hoan tat
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi dung chuong trinh
Write_I2C(0x01); //xuat dia chi thap
Wait_I2C(); //Cho hoat dong I2C hoan tat
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi dung chuong trinh
Write_I2C(0x66); //Xuat noi dung cua thanh ghi 0x0000
Wait_I2C(); //Cho hoat dong I2C hoan tat
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi dung chuong trinh
_PEN = 1; //Tao ra dieu kien STOP
Wait_I2C(); //Cho hoat dong I2C hoan tat

// doc du lieu tu ROM va goi ra cong RS232
_RSEN = 1; //Tao ra dieu kien START
Wait_I2C(); //Cho hoat dong I2C hoan tat
//Buoc 2, ghi dia chi cua ROM, sap thao tac ghi vao ROM
Write_I2C(0xA0);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi
Write_I2C(0x00);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi
Write_I2C(0x01);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi
_RSEN = 1; //Tao ra dieu kien RESTART
Wait_I2C(); //Cho hoat dong I2C hoan tat
Write_I2C(0xA1); //Ghi dia chi cua ROM, chuan bi doc tu ROM
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

temp = Read_I2C();
_PEN=1;
Wait_I2C();
U1TXREG = temp;
while(!U1STAbits.TRMT); // cho hoan tat goi byte.
while(1) Nop();
}

//Chuong trinh con khoi tao cac cong I/O
void Init_PORTS(void) {
LATC = 0xFFFF; //Tat cac LED (anode chung) noi vao cong E
TRISC = 0; //LED noi vao RC5
TRISG=0;
}

//Chuong trinh con khoi tao module I2C
void Init_I2C(void) {
I2CCON = 0x8200; //bit15=I2CEN, bit9=DISSLW (tat Slew Rate
//Control cho cac toc do baud khac 400 kbps)
I2CBRG = (((Fcy/baud) - (Fcy/1111111))-1);
}

//Chuong trinh con xuat 1 byte qua module I2C
void Write_I2C(unsigned char d) {
I2CTRN = d;
}

//Chuong trinh con cho hoat dong 00Master I2C sau cung hoan tat
void Wait_I2C(void) {
while (!_MI2CIF);
_MI2CIF = 0;
}

//Chuong trinh con xu ly khi hoat dong I2C bi loi
void I2C_Fail(void) {
_PEN = 1; //Tao ra dieu kien STOP
Wait_I2C(); //Cho hoat dong I2C hoan tat
LATC &= 0x0000; //Bat LED noi vao RE0 de bao loi
U1TXREG = 70;
while (1); //Dung chuong trinh tai day
}
unsigned char Read_I2C(void) {
unsigned char d;
_RCEN = 1; //Cho phep nhan byte
Wait_I2C(); //Cho hoat dong I2C hoan tat
d = I2CRCV; //Lay byte da nhan dat vao d
_ACKEN = 1; //Ghi bit ACK/NACK ra I2C bus
Wait_I2C(); //Cho hoat dong I2C hoan tat
return d; //Tra byte da doc ve chuong trinh goi
}

em xin lỗi vì code hơi dài, nhưng em không hiểu nó sai chỗ nào đành phải gởi lên cho mọi người xem giúp.
Các hàm đọc/ghi I2C em là tương tự TUT4 của anh namqn. Fcy của em là 7372800, baud của I2C = 100khz.
Các chân A0, A1, A2 của ROM em đã nối mass, nên địa chỉ của ROM là A0(ghi) và A1(đọc)
Module UART thì chắc ko sai, vì em đã thử các ví dụ khác, truyền và nhận rất tốt, tốc độ baud cũng ko sai, em đã kiểm tra kỹ, hơn nữa em nghi nếu sai tốc độ baud thì nó sẽ nhận được các ký tự lạ, đằng này không nhận được gì trên máy tính.
ROM thì chắc ko chết, vì em đã mua một con mới về thử :D.
Vậy có ai biết xin góp ý giúp em, hoặc có một ví dụ nào đó cụ thể về đọc ghi ROM 24c512 thì cho em xin để tham khảo, em cám ơn rất nhiều.

namqn
31-10-2009, 07:47 AM
Không thể ghi vào 24C512 rồi đọc ra ngay đâu bạn, cần có khoảng 5 ms để EEPROM hoàn tất thao tác ghi. Sau khi chờ tối thiểu 5 ms, bạn tạo điều kiện START chứ không dùng RESTART được nhé.

Thân,

npbaoduy
31-10-2009, 10:08 AM
Em đã thử rồi, sau khi ghi vào ROM, cho I2C stop, timer chạy, mỗi lần ngắt sau 0.5s mới start i2c và đọc từ rom, nhưng nó chỉ đọc được giá trị 0. Phần giao tiếp I2C thì ko báo lỗi, vì nếu báo lỗi, chương trình sẽ dừng khi vào hàm I2C_Fail(), đằng này chương trình vẫn chạy (có led nhấp nháy và cứ sau mỗi 0.5s đều gởi ra cổng nối tiếp giá trị 0).

void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
_LATC4 ^= 1; //Lat trang thai LED
_SEN = 1; //Tao ra dieu kien START
Wait_I2C(); //Cho hoat dong I2C hoan tat

Write_I2C(0xA0);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

Write_I2C(0x00);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi
Write_I2C(0x01);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

_RSEN = 1; //Tao ra dieu kien RESTART
Wait_I2C(); //Cho hoat dong I2C hoan tat

Write_I2C(0xA1); //Ghi dia chi cua ROM, chuan bi doc tu ROM
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

temp = Read_I2C();
_PEN=1;
Wait_I2C();
U1TXREG = temp;
while (!U1STAbits.TRMT);
}

Nhân tiện đây em cũng xin hỏi, điều kiện start và restart khác nhau như thế nào?
Em xin cám ơn

namqn
31-10-2009, 11:34 AM
Em đã thử rồi, sau khi ghi vào ROM, cho I2C stop, timer chạy, mỗi lần ngắt sau 0.5s mới start i2c và đọc từ rom, nhưng nó chỉ đọc được giá trị 0. Phần giao tiếp I2C thì ko báo lỗi, vì nếu báo lỗi, chương trình sẽ dừng khi vào hàm I2C_Fail(), đằng này chương trình vẫn chạy (có led nhấp nháy và cứ sau mỗi 0.5s đều gởi ra cổng nối tiếp giá trị 0).

void _ISR _T1Interrupt(void) {
_T1IF = 0; //Xoa co ngat
_LATC4 ^= 1; //Lat trang thai LED
_SEN = 1; //Tao ra dieu kien START
Wait_I2C(); //Cho hoat dong I2C hoan tat

Write_I2C(0xA0);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

Write_I2C(0x00);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi
Write_I2C(0x01);
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

_RSEN = 1; //Tao ra dieu kien RESTART
Wait_I2C(); //Cho hoat dong I2C hoan tat

Write_I2C(0xA1); //Ghi dia chi cua ROM, chuan bi doc tu ROM
if (_ACKSTAT) I2C_Fail(); //Neu NACK thi xu ly loi

temp = Read_I2C();
_PEN=1;
Wait_I2C();
U1TXREG = temp;
while (!U1STAbits.TRMT);
}

Nhân tiện đây em cũng xin hỏi, điều kiện start và restart khác nhau như thế nào?
Em xin cám ơn
Bạn nên thử với các tốc độ baud thấp, đừng thử với tốc độ tương đương tốc độ tối đa ghi trong datasheet của linh kiện.

START có đường truyền ở trạng thái idle đủ lâu, còn RESTART bao gồm STOP đi liền với START (tức là đường truyền không ở trạng thái idle đủ lâu như trường hợp START).

Thân,

npbaoduy
31-10-2009, 01:15 PM
Cám ơn anh nhiều.
Nhưng em nghĩ tốc độ 100khz là nhỏ nhất rồi chứ? Trong datasheet em thấy có 1khz, 4khz và 1mhz lận :D.
Chắc em sẽ mua một con dsPIC mới về thử, biết đâu nó bị hư gì đấy, về sơ đồ kết nối thì em kiểm tra kỹ rồi, có điện trở 4.7k kéo lên nguồn nữa, loay hoay gần cả tuần mà vẫn chưa giải quyết được.
Nếu có ai đã từng giao tiếp với ROM này được, có thể cho em xin xem qua để tham khảo nhé.
Chúc mọi người vui vẻ.

harakiri
04-11-2009, 01:36 PM
Em muốn gửi một loạt các chuỗi qua UART như "TC", delay 1 khoảng rồi gửi "RC m x y z k t" ( với m x y z k t là số thập phân) ,rồi "M". Tuy nhiên thanh ghi UxTXREG ( em dùng dsPIC33FJ64GP710) chỉ có 4 bộ đệm, như vậy em phải thiết lập thế nào các thanh ghi để gửi.

npbaoduy
08-11-2009, 01:02 AM
Vấn đề ROM vẫn mò chưa ra :D, hôm nay em lại gặp một vấn đề thế này:
U1TXREG=0x00;
while(!U1STAbits.TRMT);
U1TXREG=0x41;
while(!U1STAbits.TRMT);
thì trên máy tính chỉ nhận được giá trị 0, không nhận được 0x41 (ký tự A), em sử dụng VB, thấy không in ra được ký tự nào cả, dùng hàm lấy mã ascii chỉ thấy số 0.
còn nếu thay:
U1TXREG=0x01; //có thể là một giá trị nào đó bất kỳ khác 0
while(!U1STAbits.TRMT);
U1TXREG=0x41;
while(!U1STAbits.TRMT);
thì trên máy tính nhận được cả 2 giá trị (hiển thị được cả 2 ký tự).
Em không hiểu chỗ này, không lẽ khi gởi giá trị 0, bit U1STAbits.TRMT không được bật lên sau khi đã truyền xong hay sao?
Nếu thay bằng:
U1TXREG=0x00;
delay_ms(100);
U1TXREG=0x41;
while(!U1STAbits.TRMT);
thì nhận được cả số 0 và số 0x41, nhưng điều kiện là delay_ms phải đủ lớn, nếu delay_ms(1) thì cũng ko nhận được số 0x41 (quan sát thấy y như trường hợp đầu tiên).

harakiri
11-11-2009, 06:13 PM
Giả sử em nhận được về chip một chuỗi các kí tự " T a1 a2 a3 a4 a5"(a1,a2,a3... là số thập phân có 2 hoặc 3 chữ số nhưng bây giờ nó đang được xem là một chuỗi ký tự). Bây giờ em muốn tách chuỗi ký tự này thành một chuỗi a1 ,a2 ,a3....với a1,a2,a3 được xem là số. Liệu có hàm nào làm được điều này không?

mtuankct
11-11-2009, 10:05 PM
Theo mình chẳng có hàm nào làm được cả, cái này do bạn tự quy định thôi mà, nó phụ thuộc vào dữ liệu của bạn. Đơn giản nhất theo mình là cứ quy định mỗi số chiếm 2 byte hoăc 3byte tùy bạn

namqn
11-11-2009, 10:27 PM
Giả sử em nhận được về chip một chuỗi các kí tự " T a1 a2 a3 a4 a5"(a1,a2,a3... là số thập phân có 2 hoặc 3 chữ số nhưng bây giờ nó đang được xem là một chuỗi ký tự). Bây giờ em muốn tách chuỗi ký tự này thành một chuỗi a1 ,a2 ,a3....với a1,a2,a3 được xem là số. Liệu có hàm nào làm được điều này không?
Chuỗi ký tự khác chuỗi số của bạn ở chỗ nào?

Nếu tôi đoán không lầm, bạn muốn chuyển các tham số a1 a2 ... thành các giá trị số sau khi nhận được từ bên ngoài. Trong trường hợp này (giả sử bạn đang dùng C30), mỗi chuỗi ai có thể được dùng làm đối số cho hàm C chuẩn atoi() (sẽ cần #include <stdlib.h>). Đề nghị tham khảo tài liệu hướng dẫn !16-bit Language Tools Libraries" (DS51456) của Microchip.

Thân,

harakiri
12-11-2009, 12:22 AM
Ý của em là khi em gọi thành phần thứ 2 trong mảng, nó sẽ xuất ra cho em là a1(không kể khoảng trắng là ký tự) và a1,a2 ta không biết trước bao nhiêu ký tự.
Em dúng khoảng trắng để nhận biết nó, cuối cùng đã nhận được.
Cám ơn anh đã quan tâm trả lời giùm em.

harakiri
05-12-2009, 02:00 PM
#include <p33FJ256GP710.h>
#include <stdlib.h>
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);

#define TRUE 1
#define FALSE 0
unsigned char S2Flag, S3Flag, S4Flag, S5Flag;

unsigned int on_off ,time_out,j,t,i,x1,k;
unsigned char input[50];
unsigned char getc();
void putc(unsigned char value);
unsigned char* GetWord(unsigned char a[], int size, int index);
/************************************************** *********/
void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
input[0]=getc();
j=0;
if(input[0]=='T'||input[0]=='S')
{
while(input[j]!='r')
{
j++;
input[j]=getc();

}

U2STAbits.OERR = 0;
IFS1bits.U2RXIF = 0; //Clear the UART1 transmitter interrupt flag
on_off=1;
}
}
/************************************************** **********/
void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
input[0]=getc();
j=0;
if(input[0]=='T'||input[0]=='S')
{
while(input[j]!='r')
{
j++;
input[j]=getc();

}

U1STAbits.OERR = 0;
IFS0bits.U1RXIF = 0; //Clear the UART1 transmitter interrupt flag
on_off=1;
}
}
/************************************************** ************/
void __attribute__ ((interrupt, no_auto_psv)) _U2TXInterrupt(void) {
IFS1bits.U2TXIF = 0;

}
/************************************************** ************/
void __attribute__ ((interrupt, no_auto_psv)) _U1TXInterrupt(void) {
IFS0bits.U1TXIF = 0;
}
/************************************************** *************/
void InitClock() {
PLLFBD = 38; // M = 40
CLKDIVbits.PLLPOST = 0; // N1 = 2
CLKDIVbits.PLLPRE = 0; // N2 = 2
OSCTUN = 0;//khong su dung oscillator tuning register
RCONbits.SWDTEN = 0; // disabe watch dog timer

// Clock switch to incorporate PLL
__builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
// luu y : doc thanh ghi OSCCON de thay
__builtin_write_OSCCONL(0x01); // Start clock switching
//ghi lan luot vao 8 bit cao va thap cua OSCCON
while (OSCCONbits.COSC != 0b001); // Wait for Clock switch to occur

while(OSCCONbits.LOCK != 1) {}; //pll lock status bit
}
/************************************************** **************/
void Init_UART1 (void)
{
int i;
U1MODE = 0x0000; //Clear UART1 registers
U1STA = 0x0000;

U1BRG=20; //set baud rate

U1MODEbits.PDSEL = 0; //8bits, no parity
U1MODEbits.STSEL = 0; //1stop bit
U1MODEbits.ABAUD = 0; //No autobaud
U1MODEbits.BRGH = 0; //Low speed

U1STAbits.UTXISEL0 = 0;
U1STAbits.UTXISEL1 = 1;
U1STAbits.URXISEL = 0;

IEC0bits.U1TXIE = 1; // Enable UART Tx interrupt
IEC0bits.U1RXIE = 1;
U1MODEbits.UARTEN = 1; // Enable UART
IFS0bits.U1RXIF = 0;
IFS0bits.U1TXIF = 0;
U1STAbits.UTXEN = 1; // Enable UART Tx
/* wait at least 104 usec (1/9600) before sending first char*/
for(i = 0; i < 4160; i++)
{
Nop();
}

}
/************************************************** ********************/
void Init_UART2 (void)
{
int i;
U2MODE = 0x0000; //Clear UART1 registers
U2STA = 0x0000;

U2BRG=20; //set baud rate

U2MODEbits.PDSEL = 0; //8bits, no parity
U2MODEbits.STSEL = 0; //1stop bit
U2MODEbits.ABAUD = 0; //No autobaud
U2MODEbits.BRGH = 0; //Low speed

U2STAbits.UTXISEL0 = 0;
U2STAbits.UTXISEL1 = 1;
U2STAbits.URXISEL = 0;

IEC1bits.U2TXIE = 1; // Enable UART Tx interrupt
IEC1bits.U2RXIE = 1;
U2MODEbits.UARTEN = 1; // Enable UART
IFS1bits.U2RXIF = 0;
IFS1bits.U2TXIF = 0;
U2STAbits.UTXEN = 1; // Enable UART Tx
/* wait at least 104 usec (1/9600) before sending first char*/
for(i = 0; i < 4160; i++)
{
Nop();
}

}
/************************************************** ***************************/
void InitPorts() {
//ODCFbits.ODCF3 = 1;
//ODCFbits.ODCF5 = 1;
// S2 (portB Pin 3, chosen as trigger for sending ... to UART)
// S3 (portB Pin 2, chosen as trigger for sending ... to UART)
// S4 (portB Pin 1, chosen as trigger for sending ... to UART)
// S5 (portB Pin 0, chosen as trigger for sending ... to UART)
AD1PCFGLbits.PCFG0 = 1; // This is important. RB0 is muxxed with AN0,
// So we need to config the pin as DIGITAL
AD1PCFGLbits.PCFG1 = 1;
AD1PCFGLbits.PCFG2 = 1;
AD1PCFGLbits.PCFG3 = 1;
AD2PCFGLbits.PCFG0 = 1; // This is important. RB0 is muxxed with AN0,
// So we need to config the pin as DIGITAL
AD2PCFGLbits.PCFG1 = 1;
AD2PCFGLbits.PCFG2 = 1;
AD2PCFGLbits.PCFG3 = 1;
TRISB = 0x000F; //B0&B1&B2&B3 is input

S2Flag = S3Flag = S4Flag = S5Flag = 0; // Some Debounce Flags
}
/************************************************** *****************************/


/************************************************** ***********************/

int main(void) {
InitPorts();
InitClock(); // This is the PLL settings
Init_TMR1();
Init_UART1(); // Initialize UART1 for 9600,8,N,1 TX/RX
Init_UART2(); // Initialize UART1 for 9600,8,N,1 TX/RX


while (1)
{

if (on_off == 1)
{
on_off = 0;
// Chuong trinh xuat ra thanh phan thu 1 cua chuoi
int index = 1;
int i=0;
int j=0;
int wordIndex = 0;
unsigned char a[5];
while(i<50 || a[i] != 'r')
{
if(input[i] == ' ')
{
wordIndex++;
i++;
}
if(wordIndex == index)
{
a[j] = input[i];
j++;
}
i++;
}
a[j] = ' ';

i=0;
while (a[i] != ' ')
{
int x = atoi(a);
delay_ms(10);
x1 = x;
//putc(a[i]);
i++;

}
// Chuong trinh xuat ra thanh phan thu 7 cua chuoi
int index1 = 7;
int i1=0;
int j1=0;
int wordIndex1 = 0;
unsigned char a1[5];
while(i1<50 || a1[i1] != 'r')
{
if(input[i1] == ' ')
{
wordIndex1++;
i1++;
}
if(wordIndex1 == index1)
{
a1[j1] = input[i1];
j1++;
}
i1++;
}
a1[j1] = ' ';

i1=0;
while (a1[i1] != ' ')
{
int y = atoi(a1);
delay_ms(100);
delay_ms(100);
delay_ms(100);
t=y;
//putc(a1[i1]);
i1++;

}
k= t/2 + x1*2;
putc(k);

}
}

}

/************************************************** *****************************************
//Function: void Init_TMR1(void)
//Input: None
//Output: Setup Parameter to Timer1 Operate
// TMR1 use for delay
************************************************** *****************************************/
void Init_TMR1(void)
{
T1CONbits.TON=0; //Stop Timer1
T1CONbits.TGATE=0; //Disable Gated Timer mode
T1CONbits.TCKPS=0; //Select Prescale 1:1
T1CONbits.TCS=0;
_T1IF=0;
_T1IE=1;
TMR1=0;
}
/************************************************** *****************************************
//Function: void delay_us(unsigned int n)
//Input: n: n us to delay
//Output: Delay n us
************************************************** *****************************************/
void delay_us(unsigned int n)
{
PR1=n*40;
time_out=0;
T1CONbits.TON=1;
while(time_out==0);
T1CONbits.TON = 0;
TMR1=0;
}
/************************************************** *****************************************
//Function: void delay_ms(unsigned int n)
//Input: n: n ms to delay
//Output: Delay n ms
************************************************** *****************************************/
void delay_ms(unsigned int n)
{
unsigned int i;
i=0;
while(i<=n)
{
delay_us(1000);
i++;
}
}
void _ISR _T1Interrupt(void)
{
_T1IF = 0; //Clear Timer1 flag
time_out = 1;
}

/************************************************** ***********************/

void putc(unsigned char value)
{
while (U2STAbits.UTXBF);
U2TXREG=value;
}

/************************************************** **************************/

unsigned char getc()
{

while (!U2STAbits.URXDA);

return U2RXREG;
}



Đây là đoạn chương trình em định dung 2 module uart một lúc,nhưng khi chạy thử,gửi từ uart2 thì có lúc gửi, lúc không, em đoán là hàm ngat có vấn đề. Mong mọi người xem giúp

greenfield
20-12-2009, 08:18 PM
Anh Nam ơi cho em hỏi 2 dòng lệnh này dùng để làm gì ạ?
_PSV=1;
PSVPAG = __builtin_psvpage(Chuoi1);

namqn
20-12-2009, 08:59 PM
Anh Nam ơi cho em hỏi 2 dòng lệnh này dùng để làm gì ạ?
_PSV=1;
PSVPAG = __builtin_psvpage(Chuoi1);
_PSV = 1; dùng để cho phép sử dụng chế độ PSV. Còn dòng thứ hai thiết lập địa chỉ trang PSV cho thích hợp để có thể truy xuất chuỗi Chuoi1.

Về chế độ PSV, bạn tìm kiếm trong diễn đàn với từ khóa "PSV", đã có bạn hỏi về PSV và tôi đã trả lời.

Thân,

greenfield
21-12-2009, 09:12 PM
Anh Nam cho em hởi cái này. Sao em cài 2 module UART1 và UART2. Cụ thể em lấy U1RX nhận dữ liệu từ cổng COM và U2TX để gửi dữ liệu nhận được về máy tính mà không được. Mong anh Nam chỉ giúp em!

namqn
21-12-2009, 10:30 PM
Anh Nam cho em hởi cái này. Sao em cài 2 module UART1 và UART2. Cụ thể em lấy U1RX nhận dữ liệu từ cổng COM và U2TX để gửi dữ liệu nhận được về máy tính mà không được. Mong anh Nam chỉ giúp em!
Không hiểu câu hỏi của bạn: Cổng COM nối vào U1RX là thiết bị gì?

Sơ đồ mạch ứng dụng của bạn ra sao? Code liên quan đến 2 module UART như thế nào?

Thân,

greenfield
21-12-2009, 11:25 PM
Cụ thể em dùng dsPIC30F4013 dùng UART1 nhận dữ liệu từ máy tính và trả ký tự nhận được về máy tính qua module UART2 thử được không. Ý của em là dùng một lúc 2 module UART của dsPIC30F4013 đó mà. Em dùng Hyper Terminal của Win

namqn
22-12-2009, 07:37 AM
Cụ thể em dùng dsPIC30F4013 dùng UART1 nhận dữ liệu từ máy tính và trả ký tự nhận được về máy tính qua module UART2 thử được không. Ý của em là dùng một lúc 2 module UART của dsPIC30F4013 đó mà. Em dùng Hyper Terminal của Win
Vậy bạn kết nối phần cứng ra sao? Và code liên quan đến 2 module như thế nào? (Đừng nên để người muốn giúp bạn phải lặp lại những câu hỏi thu thập thông tin nhiều lần).

Thân,

tahi
15-01-2010, 11:33 AM
dsPIC33 ko nhận được uart.
phần cứng dspic33fj128 nối với max232 (loại smd cấp nguồn 3v3)
truyển từ dspic lên pc thì ngon
nhưng truyền từ pc xuống dspic thì ngỏm. Có xung rất đẹp đến chân nhận của dspic

chân truyền nhận đã được remappable.
Khi cấu hình loopback thì đường truyền 1 chuỗi ký tự !!!!!!!!!. Để loopback thì bít U1STAbits.URXDA có được bật lên, nếu để ngắt thì cũng có nhảy vào ngắt nhận

nhưng nếu ko dùng loopback thì bít U1STAbits.URXDA ko bật lên, mà cũng chẳng vào ngắt, mặc dù có xung ở nhân nhận

//Remap
//UART1 TX1 RP3-3 RPOR1 ; RX1 RP2 RPINR18
_RP3R = 0x03; //RP3 is UART1 output RB3
_U1RXR = 0x02; //RP2 is uart1 input RB2


/* check for receive errors */
if(U1STAbits.FERR == 1)
{
lcd_putchar('?');
}
/* must clear the overrun error to keep uart receiving */
if(U1STAbits.OERR == 1)
{
U1STAbits.OERR = 0;
lcd_putchar('?');
}
/* get the data */
while(U1STAbits.URXDA)
{
ReceivedChar = U1RXREG;
_LATA10 =~ _LATA10;
}

shinosuke
25-05-2010, 05:36 PM
Em đang thử làm giao tiếp RS232 qua 1 bộ wireless. Truyền nhận có dây lên terminal thì ok, nhưng cứ cắm bộ không dây vào thì không có tín hiệu. Có ai biết nguyên nhân có thể là do đâu không ạ ?
-----
Đi lại dây ở cổng COM lại chạy tốt rồi :D

channan
20-09-2010, 11:37 AM
Chào các bạn

Mẹo vặt để tính BRG có làm tron 1 số sau dấu chấm thập phân
vd: Sau khi tính BRG = 12.1 làm tròn 12
BRG = 15.5 làm tròn 16
//define in UART header file

#define XTAL (7372800UL) //ETT board has 7.7328Mhz XT crystal
#define PLL (16) //Clock source = Primary XT and PLL_16
#define FOSC (XTAL*PLL)
#define FCY ((FOSC)/4) //Intrustion frequency

#define BAUD_RATE 115200UL //UART baud rate
//UART1 brg value
U1BRG = ((FCY / BAUD_RATE) + 8) / 16;

channan
20-09-2010, 11:58 AM
Chào bạn

Cho tôi hỏi ngoài đề 1 chút:
Làm sao viết source code ở trong các bài post lên vậy?
Cẩm ơn !

HoanNguyenHuu
09-04-2012, 12:42 PM
Chào các bác!!!
Hiện tại em có đang làm về truyền thông RS485 theo giao thức modbus để truyền thông giữa bộ điều khiển slave (dựa trên VĐK DSPIC30F4011) và phần mềm modbusmaster.
Có bác nào làm về vấn đề này, hay có code mẫu cũng như tài liệu có thể share giúp mình được không??? em đang gặp rất nhiều khó khăn với đề tài này.
Cảm ơn các bác nhiều!!!

HoanNguyenHuu
15-04-2012, 12:41 AM
Đợi mãi không thấy bác nào lên tiếng, nản quá?

sputnhic11
08-05-2012, 11:38 PM
Em đang làm cái đồ án dùng chip dspic30f4013, bài lập trình thì ngon rùi nhưng phần khai báo vào ra để lắp nút ấn mà em chịu. Em định cho nút ấn ở port F thui vì các port khác em dùng rùi. em gửi đoạn code mong các bác chỉ giúp khai báo ở chỗ nào nhé:


/************************************************** *****************************
; timer1.c la chuong trinh viet bang C de chay tren mot dsPIC *
; Chuong trinh thuc hien viec sau: *
; Su dung Time 1 de tao xung nhip 20ms va thoi gian duty Cryle *
************************************************** ******************************
| __________
| | | |
| | | |
|____| |________________________________________|
<--1,5ms-->
<----------------------20ms------------------------->
; Tac gia : Luu Tuan Khanh *

; Don vi : Uneti *

; Ten tap tin : ltchuan.c *

; Ngay : 23/5/2011 *

; Phien ban : 0.01 *

; Nhung tap tin can thiet khac: p30F4013.gld, p30f4013.h *

; Cong cu duoc dung: MPLAB X IDE beta6.00.01 *
; C30 3.25 * *

------------------------------------------------------------------------------*/
#include <p30fxxxx.h>
#include <timer.h>
/************************************************** ****************************/
//output SERVO
#define LAT_SERVO1 _LATB0
#define LAT_SERVO2 _LATB1
#define LAT_SERVO3 _LATB2
#define LAT_SERVO4 _LATB3
#define LAT_SERVO5 _LATB4
#define LAT_SERVO6 _LATB5

#define LAT_SERVO7 _LATB6
#define LAT_SERVO8 _LATB7
#define LAT_SERVO9 _LATB8
#define LAT_SERVO10 _LATC13
#define LAT_SERVO11 _LATC14
#define LAT_SERVO12 _LATD9
#define congtac1 _TRISF0
#define congtac2 _TRISF1
#define den _LATB9

/*********************Bat dau khai bao bien*************************/
unsigned long counter_servo = 1;
unsigned int speed_servo[13];
//--------------------Ket thuc khai bao bien------------------------//
void config_servo(void);
void timer1_init(void);
int goc(float goc);

void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void){
IFS0bits.T1IF = 0; //truoc khi ra ngoai thi thi xoa bit _T1IF
T1CONbits.TON = 1;
//timer for 1us*20000=20ms
//1ms=1000 thuc te xxx min
//test 0.5ms - 2.4ms tuong ung voi 1-180do //Do thuc te
if(++counter_servo > 2010) counter_servo = 0;
if(counter_servo >= speed_servo[1] + 62) // MAX 240
LAT_SERVO1=0; // MIN 60
else
LAT_SERVO1=1; // MIN 60
if(counter_servo >= speed_servo[2] + 62) // MAX 240
LAT_SERVO2=0; // MIN 60
else
LAT_SERVO2=1;
if(counter_servo >= speed_servo[3] + 62) // MAX 240
LAT_SERVO3=0; // MIN 60
else
LAT_SERVO3=1;
if(counter_servo >= speed_servo[4] + 62) // MAX 240
LAT_SERVO4=0; // MIN 60
else
LAT_SERVO4=1;
if(counter_servo >= speed_servo[5] + 62) // MAX 240
LAT_SERVO5=0; // MIN 60
else
LAT_SERVO5=1;
if(counter_servo >= speed_servo[6] + 62) // MAX 240
LAT_SERVO6=0; // MIN 60
else
LAT_SERVO6=1;
if(counter_servo >= speed_servo[7] + 62) // MAX 240
LAT_SERVO7=0; // MIN 60
else
LAT_SERVO7=1; // MIN 60
if(counter_servo >= speed_servo[8] + 62) // MAX 240
LAT_SERVO8=0; // MIN 60
else
LAT_SERVO8=1;
if(counter_servo >= speed_servo[9] + 62) // MAX 240
LAT_SERVO9=0; // MIN 60
else
LAT_SERVO9=1;
if(counter_servo >= speed_servo[10] + 62) // MAX 240
LAT_SERVO10=0; // MIN 60
else
LAT_SERVO10=1;
if(counter_servo >= speed_servo[11] + 62) // MAX 240
LAT_SERVO11=0; // MIN 60
else
LAT_SERVO11=1;
if(counter_servo >= speed_servo[12] + 62) // MAX 240
LAT_SERVO12=0; // MIN 60
else
LAT_SERVO12=1;
}

void config_servo(void){
ADPCFG = 0xffff;
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x00;
TRISF = 0x00;

LATB = 0x00;
LATC = 0x00;
LATD = 0x00;
LATF = 0x00;

}
void timer1_init(void)
{
config_servo();
T1CON = 0; // Timer reset
T1CONbits.TSIDL = 0; //hoat dong ngay ca o che do ngu
T1CONbits.TGATE = 0; //Gated time accumulation enabled(TCS must be set to ‘0’ when TGATE = 1. Reads as ‘0’ if TCS = 1)
//T1CONbits.TSYNC = 0; //bit nay duoc bo qua khi bit TCS = 0; chi quan tam khi TCS = 1;
IFS0bits.T1IF = 0; // Reset Timer1 interrupt flag
IPC0bits.T1IP = 0b111; // Timer1 Interrupt priority level=7 // muc uu tien 7//quan trong
IEC0bits.T1IE = 1; // Enable Timer1 interrupt

T1CONbits.TCKPS = 0b00; // Bo chia tan so 1 : 1

TMR1 = 0x0000;
PR1 = 295 ; // Ngat khi dem tran 10us
//PR1 = 29491 ; // ngat khi dem tran 1ms
// T = (1/Fosc)s ma Fosc = (XTFREQ * PLL) /4
// PR1 = 29.4912 * 1 * 1 cycle (33.9084201388888888888888ns) = 1 us
T1CONbits.TCS = 0; // Timer1 Clock= Internal // Internal clock (FOSC/4)
T1CONbits.TON = 1; // Enable Timer1 and start the counter
}
int goc(float goc){
float goc1 = 0;
unsigned int goc2 = 0;
if(goc == 0) return 0;
else{
goc1 = 18 * goc;
goc1 = goc1/18;
goc2 = (int) goc1;
};
return goc2;
}

daibang1208
09-05-2012, 10:55 AM
Các anh chị và các bạn cho mình hỏi tại sao khi mình thay đổi tốc độ baud từ 38400 trong ví dụ của anh Nam thành 9600:
cũ:U1BRG =1(((8000000/38400)/16)-1);
Thành: U1BRG =1(((8000000/9600)/16)-1);
và thay đổi tốc đọ baud của VB thì ký tự nhận được bị lỗi.