久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標(biāo)題:
stm32F407單片機(jī)實現(xiàn)RS485通訊程序,同時modbus從機(jī)測試,用串口3實現(xiàn)
[打印本頁]
作者:
li64331218
時間:
2023-3-30 22:45
標(biāo)題:
stm32F407單片機(jī)實現(xiàn)RS485通訊程序,同時modbus從機(jī)測試,用串口3實現(xiàn)
pcb1.png
(3.63 MB, 下載次數(shù): 64)
下載附件
2023-3-30 22:42 上傳
自己畫的板子,用串口3 (PD8,PD9實現(xiàn),PB15收發(fā)選擇電平)。
stm32F407單片機(jī)源程序如下:
/*485-2 */
#define RS485_RE_GPIO_PORT GPIOB
#define RS485_RE_GPIO_PIN SYS_GPIO_PIN15
#define RS485_RE_GPIO_CLK_ENABLE() do{ RCC->AHB1ENR |= 1 << 1; }while(0) /* PB口時鐘使能 */
#define RS485_TX_GPIO_PORT GPIOD
#define RS485_TX_GPIO_PIN SYS_GPIO_PIN8
#define RS485_TX_GPIO_AF 7 /* AF功能選擇 */
#define RS485_TX_GPIO_CLK_ENABLE() do{ RCC->AHB1ENR |= 1 << 3; }while(0) /* PD口時鐘使能 */
#define RS485_RX_GPIO_PORT GPIOD
#define RS485_RX_GPIO_PIN SYS_GPIO_PIN9
#define RS485_RX_GPIO_AF 7 /* AF功能選擇 */
#define RS485_RX_GPIO_CLK_ENABLE() do{ RCC->AHB1ENR |= 1 << 3; }while(0) /* PD口時鐘使能 */
#define RS485_UX USART3
#define RS485_UX_IRQn USART3_IRQn
#define RS485_UX_IRQHandler USART3_IRQHandler
#define RS485_UX_CLK_ENABLE() do{ RCC->APB1ENR |= 1 << 18; }while(0) /* USART3 時鐘使能 */
/*485-2 END */
/* 控制RS485_RE腳, 控制RS485發(fā)送/接收狀態(tài)
* RS485_RE = 0, 進(jìn)入接收模式
* RS485_RE = 1, 進(jìn)入發(fā)送模式
*/
#define RS485_RE(x) sys_gpio_pin_set(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, x)
#define RS485_REC_LEN 64 /* 定義最大接收字節(jié)數(shù) 64 */
#define RS485_EN_RX 1 /* 使能(1)/禁止(0)RS485接收 */
extern uint8_t g_RS485_rx_buf[RS485_REC_LEN]; /* 接收緩沖,最大RS485_REC_LEN個字節(jié) */
extern uint8_t g_RS485_rx_cnt; /* 接收數(shù)據(jù)長度 */
void rs485_init(uint32_t sclk, uint32_t baudrate); /* RS485初始化 */
void rs485_send_data(uint8_t *buf, uint8_t len); /* RS485發(fā)送數(shù)據(jù) */
void rs485_receive_data(uint8_t *buf, uint8_t *len);/* RS485接收數(shù)據(jù) */
extern void UartDriver(void); /* 485接收數(shù)據(jù)處理 */
#endif
//串口驅(qū)動函數(shù),檢測數(shù)據(jù)幀的接收,調(diào)度功能函數(shù),需在主循環(huán)中調(diào)用
void UartDriver(void)
{
unsigned char i=0,cnt;
unsigned int crc;
unsigned char crch,crcl;
static uint8_t len;
static uint8_t buf[60];
if(flagFrame) //幀接收完成標(biāo)志,即接收到一幀新數(shù)據(jù)
{
flagFrame=0; //幀接收完成標(biāo)志清零
len = UartRead(buf,sizeof(buf)); //將接收到的命令讀到緩沖區(qū)中
if(buf[0]==0x01) //判斷地址是不是0x01
{
crc=GetCRC16(buf,len-2); //計算CRC校驗值,出去CRC校驗值
crch=crc>>8; //crc高位
crcl=crc&0xFF; //crc低位
if((buf[len-2]==crch)&&(buf[len-1]==crcl)) //判斷CRC校驗是否正確
{
switch (buf[1]) //按功能碼執(zhí)行操作
{
case 0x03: //讀數(shù)據(jù)
if((buf[2]==0x00)&&(buf[3]<=0x05)) //寄存器地址支持0x0000~0x0005
{
if(buf[3]<=0x04)
{
i=buf[3];//提取寄存器地址
cnt=buf[5]; //提取待讀取的寄存器數(shù)量
buf[2]=cnt*2; //讀取數(shù)據(jù)的字節(jié)數(shù),為寄存器*2,因modbus定義的寄存器為16位
len=3;
while(cnt--)
{
buf[len++]=0x00; //寄存器高字節(jié)補(bǔ)0
buf[len++]=regGroup[i++]; //低字節(jié)
}
}
break;
}
else //寄存器地址不被支持時,返回錯誤碼
{
buf[1]=0x83; //功能碼最高位置1
buf[2]=0x02; //設(shè)置異常碼為02-無效地址
len=3;
break;
}
case 0x06: //寫入單個寄存器
if((buf[2]==0x00)&&(buf[3]<=0x05)) //寄存器地址支持0x0000-0x0005
{
if(buf[3]<=0x04)
{
i=buf[3]; //提取寄存器地址
regGroup[i]=buf[5]; //保存寄存器數(shù)據(jù)
LED0(0);
}
len -=2; //長度-2以重新計算CRC并返回原幀
break;
}
else
{ //寄存器地址不被支持,返回錯誤碼
buf[1]=0x86; //功能碼最高位置1
buf[2]=0x02; //設(shè)置異常碼為02-無效地址
len=3;
break;
}
default: //其他不支持的功能碼
buf[1]=0x80; //功能碼最高位置1
buf[2]=0x01; //設(shè)置異常碼為01—無效功能
len=3;
break;
}
crc=GetCRC16(buf,len); //計算CRC校驗值
buf[len++]=crc>>8; //CRC高字節(jié)
buf[len++]=crc&0xff; //CRC低字節(jié)
// rs485_UartWrite(buf,len); //發(fā)送響應(yīng)幀
rs485_send_data(buf,len); //發(fā)送響應(yīng)幀
}
}
}
}
void UartRxMonitor(uint8_t ms) //串口接收監(jiān)控
{
static uint8_t USART3_RX_BKP=0; //定義USART2_RC_BKP暫時存儲數(shù)據(jù)長度與實際長度比較
static uint8_t idletmr=0; //定義監(jiān)控時間
if(g_RS485_rx_cnt>0)//接收計數(shù)器大于零時,監(jiān)控總線空閑時間
{
if(USART3_RX_BKP!=g_RS485_rx_cnt) //接收計數(shù)器改變,即剛接收到數(shù)據(jù)時,清零空閑計時
{
USART3_RX_BKP=g_RS485_rx_cnt; //賦值操作,將實際長度給USART2_RX_BKP
idletmr=0; //將監(jiān)控時間清零
}
else ////接收計數(shù)器未改變,即總線空閑時,累計空閑時間
{
//如果在一幀數(shù)據(jù)完成之前有超過3.5個字節(jié)時間的停頓,接收設(shè)備將刷新當(dāng)前的消息并假定下一個字節(jié)是一個新的數(shù)據(jù)幀的開始
if(idletmr<5) //空閑時間小于1ms時,持續(xù)累加
{
idletmr +=ms;
if(idletmr>=5) //空閑時間達(dá)到1ms時,即判定為1幀接收完畢
{
flagFrame=1;//設(shè)置命令到達(dá)標(biāo)志,幀接收完畢標(biāo)志
}
}
}
}
else
{
USART3_RX_BKP=0;
}
}
/**
* @brief RS485發(fā)送len個字節(jié)
* @param buf : 發(fā)送區(qū)首地址
* @param len : 發(fā)送的字節(jié)數(shù)(為了和本代碼的接收匹配,這里建議不要超過 RS485_REC_LEN 個字節(jié))
* @retval 無
*/
void rs485_send_data(uint8_t *buf, uint8_t len)
{
uint8_t t;
RS485_RE(1); /* 進(jìn)入發(fā)送模式 */
for (t = 0; t < len; t++) /* 循環(huán)發(fā)送數(shù)據(jù) */
{
while ((RS485_UX->SR & 0X40) == 0); /* 等待發(fā)送結(jié)束 */
RS485_UX->DR = buf[t];
}
while ((RS485_UX->SR & 0X40) == 0); /* 等待發(fā)送結(jié)束 */
g_RS485_rx_cnt = 0;
RS485_RE(0); /* 進(jìn)入接收模式 */
}
/**
* @brief RS485查詢接收到的數(shù)據(jù)
* @param buf : 接收緩沖區(qū)首地址
* @param len : 接收到的數(shù)據(jù)長度
* @arg 0 , 表示沒有接收到任何數(shù)據(jù)
* @arg 其他, 表示接收到的數(shù)據(jù)長度
* @retval 無
*/
void rs485_receive_data(uint8_t *buf, uint8_t *len)
{
uint8_t rxlen = g_RS485_rx_cnt;
uint8_t i = 0;
*len = 0; /* 默認(rèn)為0 */
delay_ms(10); /* 等待10ms,連續(xù)超過10ms沒有接收到一個數(shù)據(jù),則認(rèn)為接收結(jié)束 */
if (rxlen == g_RS485_rx_cnt && rxlen) /* 接收到了數(shù)據(jù),且接收完成了 */
{
for (i = 0; i < rxlen; i++)
{
buf[i] = g_RS485_rx_buf[i];
}
*len = g_RS485_rx_cnt; /* 記錄本次數(shù)據(jù)長度 */
g_RS485_rx_cnt = 0; /* 清零 */
}
}
復(fù)制代碼
Keil代碼下載:
測試 485-2(串口3)modbus rtu從機(jī)實驗.7z
(216.49 KB, 下載次數(shù): 78)
2023-3-31 01:21 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
li64331218
時間:
2023-4-2 16:15
485通訊是半雙工的,注意收發(fā)控制引腳的電平切換。
作者:
aayon1979
時間:
2024-9-2 16:19
好東西!我來下一個
作者:
rongshengju
時間:
2024-9-18 08:22
學(xué)習(xí)!!!
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
久操精品
|
欧美理论片在线观看
|
日本成人一区二区
|
成人午夜网站
|
国产精品91在线
|
国产一区二区三区在线视频
|
影音先锋在线观看视频
|
日本毛片在线观看
|
亚洲欧美一区二区三区在线
|
日韩二区在线
|
黄色一级免费看
|
夜夜操影院
|
国产成人精品一区二区三区福利
|
国产草草
|
高清一区二区三区
|
国产在线成人
|
国产一区在线播放
|
国产黄av
|
五月天.com
|
久久成人免费视频
|
欧美日韩亚洲一区二区三区
|
午夜精品久久久久久久99
|
亚洲欧美日韩国产精品
|
日本少妇做爰全过程毛片
|
欧美aaaaa
|
在线播放国产精品
|
97国产视频
|
婷婷久久久
|
久久久久久久久国产精品
|
91女人18毛片水多国产
|
久草免费在线观看视频
|
欧美一级色
|
国产一区二区三区在线视频
|
女人高潮特级毛片
|
日本在线视频观看
|
性久久久久久
|
国产成人一区二区三区
|
丰满少妇高潮在线观看
|
国产精品一区二区在线播放
|
国产午夜精品一区二区三区视频
|
亚洲乱码在线观看
|