久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
stm32F407單片機實現RS485通訊程序,同時modbus從機測試,用串口3實現
[打印本頁]
作者:
li64331218
時間:
2023-3-30 22:45
標題:
stm32F407單片機實現RS485通訊程序,同時modbus從機測試,用串口3實現
pcb1.png
(3.63 MB, 下載次數: 64)
下載附件
2023-3-30 22:42 上傳
自己畫的板子,用串口3 (PD8,PD9實現,PB15收發選擇電平)。
stm32F407單片機源程序如下:
/*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發送/接收狀態
* RS485_RE = 0, 進入接收模式
* RS485_RE = 1, 進入發送模式
*/
#define RS485_RE(x) sys_gpio_pin_set(RS485_RE_GPIO_PORT, RS485_RE_GPIO_PIN, x)
#define RS485_REC_LEN 64 /* 定義最大接收字節數 64 */
#define RS485_EN_RX 1 /* 使能(1)/禁止(0)RS485接收 */
extern uint8_t g_RS485_rx_buf[RS485_REC_LEN]; /* 接收緩沖,最大RS485_REC_LEN個字節 */
extern uint8_t g_RS485_rx_cnt; /* 接收數據長度 */
void rs485_init(uint32_t sclk, uint32_t baudrate); /* RS485初始化 */
void rs485_send_data(uint8_t *buf, uint8_t len); /* RS485發送數據 */
void rs485_receive_data(uint8_t *buf, uint8_t *len);/* RS485接收數據 */
extern void UartDriver(void); /* 485接收數據處理 */
#endif
//串口驅動函數,檢測數據幀的接收,調度功能函數,需在主循環中調用
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) //幀接收完成標志,即接收到一幀新數據
{
flagFrame=0; //幀接收完成標志清零
len = UartRead(buf,sizeof(buf)); //將接收到的命令讀到緩沖區中
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]) //按功能碼執行操作
{
case 0x03: //讀數據
if((buf[2]==0x00)&&(buf[3]<=0x05)) //寄存器地址支持0x0000~0x0005
{
if(buf[3]<=0x04)
{
i=buf[3];//提取寄存器地址
cnt=buf[5]; //提取待讀取的寄存器數量
buf[2]=cnt*2; //讀取數據的字節數,為寄存器*2,因modbus定義的寄存器為16位
len=3;
while(cnt--)
{
buf[len++]=0x00; //寄存器高字節補0
buf[len++]=regGroup[i++]; //低字節
}
}
break;
}
else //寄存器地址不被支持時,返回錯誤碼
{
buf[1]=0x83; //功能碼最高位置1
buf[2]=0x02; //設置異常碼為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]; //保存寄存器數據
LED0(0);
}
len -=2; //長度-2以重新計算CRC并返回原幀
break;
}
else
{ //寄存器地址不被支持,返回錯誤碼
buf[1]=0x86; //功能碼最高位置1
buf[2]=0x02; //設置異常碼為02-無效地址
len=3;
break;
}
default: //其他不支持的功能碼
buf[1]=0x80; //功能碼最高位置1
buf[2]=0x01; //設置異常碼為01—無效功能
len=3;
break;
}
crc=GetCRC16(buf,len); //計算CRC校驗值
buf[len++]=crc>>8; //CRC高字節
buf[len++]=crc&0xff; //CRC低字節
// rs485_UartWrite(buf,len); //發送響應幀
rs485_send_data(buf,len); //發送響應幀
}
}
}
}
void UartRxMonitor(uint8_t ms) //串口接收監控
{
static uint8_t USART3_RX_BKP=0; //定義USART2_RC_BKP暫時存儲數據長度與實際長度比較
static uint8_t idletmr=0; //定義監控時間
if(g_RS485_rx_cnt>0)//接收計數器大于零時,監控總線空閑時間
{
if(USART3_RX_BKP!=g_RS485_rx_cnt) //接收計數器改變,即剛接收到數據時,清零空閑計時
{
USART3_RX_BKP=g_RS485_rx_cnt; //賦值操作,將實際長度給USART2_RX_BKP
idletmr=0; //將監控時間清零
}
else ////接收計數器未改變,即總線空閑時,累計空閑時間
{
//如果在一幀數據完成之前有超過3.5個字節時間的停頓,接收設備將刷新當前的消息并假定下一個字節是一個新的數據幀的開始
if(idletmr<5) //空閑時間小于1ms時,持續累加
{
idletmr +=ms;
if(idletmr>=5) //空閑時間達到1ms時,即判定為1幀接收完畢
{
flagFrame=1;//設置命令到達標志,幀接收完畢標志
}
}
}
}
else
{
USART3_RX_BKP=0;
}
}
/**
* @brief RS485發送len個字節
* @param buf : 發送區首地址
* @param len : 發送的字節數(為了和本代碼的接收匹配,這里建議不要超過 RS485_REC_LEN 個字節)
* @retval 無
*/
void rs485_send_data(uint8_t *buf, uint8_t len)
{
uint8_t t;
RS485_RE(1); /* 進入發送模式 */
for (t = 0; t < len; t++) /* 循環發送數據 */
{
while ((RS485_UX->SR & 0X40) == 0); /* 等待發送結束 */
RS485_UX->DR = buf[t];
}
while ((RS485_UX->SR & 0X40) == 0); /* 等待發送結束 */
g_RS485_rx_cnt = 0;
RS485_RE(0); /* 進入接收模式 */
}
/**
* @brief RS485查詢接收到的數據
* @param buf : 接收緩沖區首地址
* @param len : 接收到的數據長度
* @arg 0 , 表示沒有接收到任何數據
* @arg 其他, 表示接收到的數據長度
* @retval 無
*/
void rs485_receive_data(uint8_t *buf, uint8_t *len)
{
uint8_t rxlen = g_RS485_rx_cnt;
uint8_t i = 0;
*len = 0; /* 默認為0 */
delay_ms(10); /* 等待10ms,連續超過10ms沒有接收到一個數據,則認為接收結束 */
if (rxlen == g_RS485_rx_cnt && rxlen) /* 接收到了數據,且接收完成了 */
{
for (i = 0; i < rxlen; i++)
{
buf[i] = g_RS485_rx_buf[i];
}
*len = g_RS485_rx_cnt; /* 記錄本次數據長度 */
g_RS485_rx_cnt = 0; /* 清零 */
}
}
復制代碼
Keil代碼下載:
測試 485-2(串口3)modbus rtu從機實驗.7z
(216.49 KB, 下載次數: 78)
2023-3-31 01:21 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
li64331218
時間:
2023-4-2 16:15
485通訊是半雙工的,注意收發控制引腳的電平切換。
作者:
aayon1979
時間:
2024-9-2 16:19
好東西!我來下一個
作者:
rongshengju
時間:
2024-9-18 08:22
學習!!!
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
日本成人免费观看
|
国产伦精品一区二区三区精品视频
|
一区二区成人
|
91视频播放
|
亚洲国产成人精品女人久久久
|
日本中文字幕在线视频
|
欧美精品1区2区3区 精品国产欧美一区二区
|
国产日韩免费观看
|
成人高清在线视频
|
国产一区二区久久
|
超碰在线观看97
|
自拍偷拍3p
|
99久久中文字幕三级久久日本
|
久久久久久高潮国产精品视
|
亚洲高清一区二区三区
|
日韩成人av在线播放
|
美女中文字幕视频
|
精品国产乱码久久久久久影片
|
一区二区精品
|
九九九视频精品
|
2019天天干天天操
|
国产在线一区二区三区
|
亚洲一区二区三区四区在线观看
|
亚洲av毛片
|
色必久久
|
国产精品一区二区日韩
|
日韩一区二
|
国产成人99久久亚洲综合精品
|
女人精96xxx免费网站p
|
久久综合激情
|
五月激情婷婷六月
|
香蕉婷婷
|
免费中文字幕
|
久久亚洲一区二区三区四区
|
天天插天天操
|
高清国产一区二区
|
欧美日韩网站
|
精品福利在线
|
成人高清视频在线观看
|
日一区二区
|
午夜二区
|