會員登陸
帳號:

密碼:

記住我



忘記密碼?

現在註冊!
網站導航
最新下載
訪問統計 (自2012/5/3)


正在流覽:   1 名訪客





usb轉RS485下指令沒有反應/ pic16f877
新會員
註冊日期:
2012/07/19 02:31
所屬群組:
註冊會員
文章: 19
等級: 3; EXP: 9
HP : 0 / 52
MP : 6 / 978
離線
我目前想做一對多控制用USB轉RS485 ,用CCS C編譯
目前僅能印出HH.下指令卻沒有反應無法接收指令。
我該如何修改程式,下面是我的接線方式
(pc-->usb to rs485-->max485-->pic16f877)
DI=PinC6 ,RO=pinC7,DE=RE=pinC5

#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=12000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, enable = PIN_C5, stream=STREAM_UART)
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x09

#define RS485_ENABLE_PIN PIN_C5
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7

#include <rs485.c>

#include <string.h>

int8 data_received[32];
void main(void)
{ char c;
int i,n;
output_low(RS485_ENABLE_PIN);
rs485_init();
printf("HH. \r\n");
while(TRUE)
{
delay_ms(300);
if(rs485_get_message(data_received, FALSE)){
if(data_received[2] ==a)
{ printf("LL \r\n"); delay_ms(400);}
}
}
}

3月04日 22:00:34
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
新會員
註冊日期:
2012/07/19 02:31
所屬群組:
註冊會員
文章: 19
等級: 3; EXP: 9
HP : 0 / 52
MP : 6 / 978
離線
上一層樓接法是A=B ,B=A 同樣會遇下列問題。
大家好我做了一些測試,
還有遇到一問題如果我A=A,B=B接傳送資料會出現亂碼
以下面程式 H.他會顯示k,傳送字串n會回傳$這先符號,
如果我用A=B ,B=A 這樣接法一開始會顯示H.正確符號,但傳資料給資沒反應。
因為RS485找不到資料,所以直接參考msp430晶片rs485寫法。
請問我問題出在哪?

https://www.taiwaniot.com.tw/product/t ... rs485rs422-max485-module/
我max485是直接用模組

#include <16F877A.h> // PIC16F877 header file
#fuses HS, NOWDT, NOPROTECT, NOLVP // for debug mode
#device 16f877*=16, ADC=10 // 10 bits ADC
#use delay(clock=12000000) // for 8Mhz crystal
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, STREAM=STREAM_UART,errors)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=STREAM_UART)
#include <string.h>
#define LED_PIN PIN_D0

//#include <thermistorc.c>
void main(void)
{ char c;
int i,n;
n=3;
set_tris_d(0);
output_high(PIN_D0);//DE,RE
output_high(PIN_D1);//DE,RE
printf("H. \r\n");
while(TRUE)
{

if (kbhit(STREAM_UART))
{ delay_ms(100);
c = fgetc(STREAM_UART);
delay_ms(10);
if(c=='n')
{
printf("L\r\n");
output_high(PIN_D3);

}
}
}}

3月06日 02:56:17
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
資深會員
註冊日期:
2007/03/29 00:43
所屬群組:
註冊會員
文章: 183
等級: 12; EXP: 58
HP : 0 / 289
MP : 61 / 9908
離線
用 ICD 追進去不就知道了嗎?

3月06日 19:26:21
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 174
等級: 12; EXP: 24
HP : 0 / 281
MP : 58 / 7958
離線
RS485 需要注意的地方之一為:
同一時間內最多只能一個點對 RS485 線路發送資料,
否則訊號就會互相影響.

且 MAX485 這類介面 IC 也確實需要自己控制 發送/接收 狀態,

而你的程式中,
明顥的並沒有 發送 / 接收 狀態的切換,
所以, 我想你目前的最大問題應該是這個了.

你可以參考以下的資料看看.


#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=12000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=STREAM_UART)

#define RS485_DE_PIN PIN_D0
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7

#include <string.h>
// #include <rs485.h>

int8  serial_in[32];
int8  serial_len = 0;
int8  serial_ending = 0;
int16 wait_ending = 0;

void main(void)
{
  
char c;
  
int i,n;

//  output_low(RS485_DE_PIN);
//  rs485_init();

  
output_high(RS485_DE_PIN);   /* 轉為發送狀態 */
  
fprintf(STREAM_UART, "Start trying. Ha ! ha ! ");
  
delay_ms(3);
  
output_low(RS485_DE_PIN);   /* 轉為接收狀態 */

  
while(TRUE)
    {
       if(
kbhit(STREAM_UART))
         {
            
c = fgetc(STREAM_UART);   /* 取得一個輸入的字元 */
            
if(serial_len < 30 && c >= ' ' && serial_ending == 0)  serial_in[serial_len++] = c;
            
/* 把輸入接成字串 */

            
wait_ending = 5000;
            if(
c < ' ' || c == '$')  serial_ending = 1;
            
/* 是否有出現字串結束字元 rn 或 $ 等... */
         
}

       if(
wait_ending != 0 && serial_ending != 0)   /* 出現結束字元時, 等待傳送完全停止 */
         
{
            
wait_ending--;   /* 等待倒數中 */
            
if(wait_ending == 0)
              {
                 
serial_in[serial_len] = 0;   /* 把接收字串補上字串結尾 NULL */
                 
serial_len = 0;   /* 讓下次接收再重頭開始 */
                 
serial_ending = 0;   /* 清除掉字串結束的旗號, 好能重新開始 */

                 
output_high(RS485_DE_PIN);   /* 轉為發送狀態 */
                 
fprintf(STREAM_UART, "I see => %s rn", serial_in);
                 
delay_ms(3);
                 
output_low(RS485_DE_PIN);   /* 轉為接收狀態 */
              
}
         }
    }
}

附加檔案:



gif  Test-485.GIF (7.30 KB)
5620_5a9e9fdfd3cb9.gif 818X467 px

3月06日 22:04:45
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
版主
註冊日期:
2004/04/30 10:53
來自 CAE, Microchip
所屬群組:
站務管理者
註冊會員
MICROCHIP
文章: 14562
等級: 73; EXP: 15
HP : 1082 / 1803
MP : 4854 / 77079
離線
問一下,你的 RS-485 是全雙工還是半雙工的接法?

1. 全雙工無須控制腳位直接一對一對接。

2. 半雙工需控制方向。但也有兩種方式: 一是 Multi-Master 方式,平常大家都處於輸入模式,要發言時再用 CDAM/CD 檢測的方式來使用 Bus。第二種是 Single Master to Multi Slave 的方式,也是比較常用的方式。

檢查一下是否 UART 的最後一筆資料是否還沒傳完程式已經切換成輸入模式了,造成最後一筆資料無法正確傳送出去。這與程式裡在做發送時檢查 TXIF 或 TRMT 位元有關。

最簡單的方式就是使用示波器來量測,比較一下UART 的傳送形與 RS-485 的輸出是否一樣? 有沒有輸出被砍掉了。

3月07日 10:34:43
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
資深會員
註冊日期:
2007/06/05 21:45
所屬群組:
註冊會員
文章: 1014
等級: 28; EXP: 16
HP : 0 / 679
MP : 338 / 22866
離線
有時候問題出在 小細節上...
量量看終端電阻...
量量波形...等等

3月07日 14:53:46
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
新會員
註冊日期:
2012/07/19 02:31
所屬群組:
註冊會員
文章: 19
等級: 3; EXP: 9
HP : 0 / 52
MP : 6 / 978
離線
if(kbhit(STREAM_UART))
{
c = fgetc(STREAM_UART); /* 取得一個輸入的字元 */
if(serial_len < 30 && c >= ' ' && serial_ending == 0) serial_in[serial_len++] = c;
/* 把輸入接成字串 */

wait_ending = 5000;
if(c < ' ' || c == '$') serial_ending = 1;
/* 是否有出現字串結束字元 rn 或 $ 等... */
}

我有一個問題想問還有一個觀念想釐清
if(kbhit(STREAM_UART)) kbhit這個指令是用來判斷STREAM_UART這個com有沒有東西讀近來嗎? 因為網路上找的資料都是說偵測鍵盤按鍵?
這段程式在CCS 跑可以把字串讀進來並且print出來。 但是如果送hex資料print出來的東西就不對 fprintf(STREAM_UART,"%x",serial_in);
這樣應該沒錯,如果我傳FE FF 出來會變成1a...錯誤資料,照理來說字串跟hex資料傳輸應該是一樣的方法。還是說我觀念有問題,如果print char c 單一個hex就沒問題,還是說hex不能用這程式去串接?

12月04日 07:34:08
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 174
等級: 12; EXP: 24
HP : 0 / 281
MP : 58 / 7958
離線
關於 kbhit(stream) 的問題,
因為使用的是 ccs c compiler 與其提供的程式庫,
想要確知它在此的功能當然是查 ccs c 的手冊說明最實際了.
以下附上手冊中對 kbhit() 的說明節錄內容.
(大致就是你猜想的...有無資料進入 uart 被接收的狀況)

至於收發 hex 時的問題,
依你的敘述實在是難了解是何狀況,
或許你可以再試試其他的程式.
hex 收發因為使用了 00 ~ FF ,
所以把發送時連續一起的, 當成同一批數值資料,
停止超出了 "判斷時間" 時, 就判斷此次接收結束,
請注意這個部分.


#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=12000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=STREAM_UART)

#define RS485_DE_PIN PIN_D0
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7


int8  serial_out[32];
int8  serial_in[32];
int8  serial_len = 0;
int8  serial_send = 0;
int16 check_ending = 0;


#INT_RDA
void serial_isr()
{
/* UART 接收中斷處理程序 */
  
int8  c;

  
c = fgetc(STREAM_UART);   /* 取得一個輸入的字元 */
  
if(serial_len < 30)  serial_in[serial_len++] = c;
  
/* 把輸入字元依序儲存起來 */

  
check_ending = 5000;   /* 重設字元等待計數 */
}

void serial_send_block(int8  *buffer_out, int8  send_lengh)
{
/* UART 數值資料區段發送 (16進位, 2進位, 數值資料區段) */
  
int8  send_n;

  
output_high(RS485_DE_PIN);   /* 轉為發送狀態 */
  
for(send_n = 0; send_n < send_lengh; send_n++)
     {
       
fputc(buffer_out[send_n], STREAM_UART);   /* 依序發送 */
     
}
  
delay_ms(3);
  
output_low(RS485_DE_PIN);   /* 轉為接收狀態 */
}


void main(void)
{
  
int8  cc;


  
enable_interrupts(INT_RDA);   /* 使 uart 接收中斷有效 */
  
enable_interrupts(GLOBAL);   /* 使 中斷總控制有效 (中斷開始有效) */

  
output_high(RS485_DE_PIN);   /* 轉為發送狀態 */
  
fprintf(STREAM_UART, "UART  test ! ");
  
delay_ms(3);
  
output_low(RS485_DE_PIN);   /* 轉為接收狀態 */

  
while(TRUE)
    {
//
//   *** 使此區段無效, 改為中斷接收的方式 ***
//       if(kbhit(STREAM_UART))
//         {
//            c = fgetc(STREAM_UART);   /* 取得一個輸入的字元 */
//            if(serial_len < 30)  serial_in[serial_len++] = c;
//            /* 把輸入字元依序儲存起來 */
//
//            check_ending = 5000;   /* 重設字元等待計數 */
//         }

       
if(check_ending > 0)   /* 如果有接收字元, 遞減等待計數 */
         
{
            
check_ending--;   /* 倒數中 */
            
if(check_ending == 1)
              {   
/* 倒數已至最後, 此次接收資料結束, 開始接收後的處理 */
                 
serial_send = serial_len;   /* 回傳字元數 = 接收字元數 */
                 
serial_len = 0;   /* 讓下次接收再重頭開始 */

                 
for(cc = 0;  cc < serial_send; cc++)
                    {
/* 把接收資料順序翻轉後作為發送資料 */
                      
serial_out[cc] = serial_in[serial_send - cc - 1];
                    }
                 
serial_send_block(serial_out, serial_send);   /* 發送數值資料 */
                 
check_ending = 0;   /* 接收處理結束, 回復無動作狀態 */
              
}
         }
    }
}

附加檔案:



jpg  ccs-kbhit.jpg (220.18 KB)
5620_5c0e72cac3ced.jpg 909X1360 px

12月10日 22:07:00
轉換PDF檔 列印


Re: usb轉RS485下指令沒有反應/ pic16f877
資深會員
註冊日期:
2009/04/07 13:30
所屬群組:
註冊會員
文章: 174
等級: 12; EXP: 24
HP : 0 / 281
MP : 58 / 7958
離線
對了!!!
要使用接收進來的數值資料時,
必須使用 serial_in[0], serial_in[1], serial_in[N], serial_in[M] 這類的,
不可以使用 serial_in ,
因為 serial_in[N] 會取得陣列內的數值資料,
而 serial_in 取得的卻是 陣列的起始位址.

12月10日 22:33:06
轉換PDF檔 列印






無法在此發表文章
可以在此觀看文章
無法回覆文章
無法編輯自己的文章
無法刪除自己的文章
無法發起投票調查
無法在此投票
無法上傳附加檔案
無法不經審核直接發表文章

[進階搜尋]


搜尋
Microchip連結

網頁捷徑
2019 Winter Elite 報名
教育訓練
其它網站連結
電話: 02-25000405
產品技術問題產品技術支援專線:0800-717718 台北02-25088600 新竹03-5778366 Ext. 8600 高雄07-2137830 MicrochipDIRECT 專線: 07-2137830
Powered by XOOPS © 2001-2012 The XOOPS Project