PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   dsPIC - Bộ điều khiển tín hiệu số 16-bit (http://www.picvietnam.com/forum/forumdisplay.php?f=29)
-   -   dsPIC Tutorial 4-Module UART và I2C (http://www.picvietnam.com/forum/showthread.php?t=623)

namqn 18-09-2006 08:27 PM

dsPIC Tutorial 4-Module UART và I2C
 
3 Attachment(s)
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

Trích:

Nguyên văn bởi ntuan (Post 10547)
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

Trích:

Nguyên văn bởi ntuan (Post 10563)
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

Trích:

Nguyên văn bởi scentoflove (Post 10766)
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

Trích:

Nguyên văn bởi scentoflove (Post 10777)
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

1 Attachment(s)
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
Code:

#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
Code:

#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
Code:

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

Trích:

Nguyên văn bởi han_nang_008 (Post 20970)
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

Trích:

Nguyên văn bởi namqn (Post 20977)
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

Trích:

Nguyên văn bởi han_nang_008 (Post 20982)
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

Trích:

Nguyên văn bởi namqn (Post 20984)
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

Trích:

Nguyên văn bởi han_nang_008 (Post 20987)
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
Code:

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
Code:

//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

Trích:

Nguyên văn bởi han_nang_008 (Post 21403)
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/langu...onvertbase.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

Trích:

Nguyên văn bởi han_nang_008 (Post 21408)
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):
Code:

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
Code:

      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
Code:

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
Code:

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

Trích:

Nguyên văn bởi namqn (Post 22166)
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

Trích:

Nguyên văn bởi ham_hoc_hoi (Post 22188)
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

1 Attachment(s)
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

Trích:

Nguyên văn bởi conglong (Post 23576)
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

Trích:

Nguyên văn bởi conglong (Post 23578)
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

Trích:

Nguyên văn bởi namqn (Post 23592)
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

Trích:

Nguyên văn bởi namqn (Post 23593)
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

Trích:

Nguyên văn bởi conglong (Post 23616)
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

Trích:

Nguyên văn bởi conglong (Post 23617)
ý 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

Trích:

Nguyên văn bởi namqn (Post 23620)
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

Trích:

Nguyên văn bởi conglong (Post 23624)
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

Trích:

Nguyên văn bởi conglong (Post 23625)
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

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

Nguyên văn bởi namqn (Post 5002)
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

Trích:

Nguyên văn bởi KENJY (Post 24309)
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,


Múi giờ GMT. Hiện tại là 11:07 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam