讀博警告:
本人純屬小白一枚,剛開始接觸學習STM32,本篇微博只是想記錄自己在做專案中程序中遇到的問題以及最后的解決辦法,第一次更博,語言表達能力不好還很亂,望見諒,歡迎大家一起學習交流!
專案描述
要求:
1、監測設備一天的用電量,
2、統計開機、關機時間,計算使用率,
3、有可能的話實作手機端實時監控
預計方案:
STM32單片機通過RS-485串口驅動電力表模塊采集資料,然后再通過TTL串口將資料發送給ZigBee終端,ZigBee終端在接收到資料后通過無線傳輸將資料發送給協調器,ZigBee協調器通過RS232串口通訊將資料發送給上位機,上位機實時顯示資料,另外,還可以開發一款手機APP,上位機將資料保存,發送到手機端,通過手機端對資料進行實時監控,
其中,電力表模塊、STM32模塊、ZigBee終端模塊這三部分組成一個資料采集模塊,放置在機器人上,用于采集資料,ZigBee協調器模塊和上位機構成顯示模塊,用于顯示耗電量、使用效率等資料,
專案系統結構圖如下:

專案實施計劃
通信
單片機與電力表之間通過串口1通訊,上位機與單片機之間通過串口2通訊 ,
串口1、2的初始化程式、中端配置程式如下:
//串口1初始化函式
void usart1_init(u32 bound)
{
//GPIO埠設定
GPIO_InitTypeDef GPIO_InitStructure;//創建GPIO的初始化結構體
USART_InitTypeDef USART_InitStructure;//創建USART的初始化結構體
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 RX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//USART 初始化設定
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位資料格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬體資料流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
}
//串口1中斷配置
void usart1_NVIC__init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;//創建NVIC的初始化結構體
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據指定的引數初始化VIC暫存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷
}
void usart2_init(u32 bound)
{
//GPIO埠設定
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2 tx
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3 Rx
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART2配置
USART_InitStructure.USART_BaudRate = bound;//波特率設定
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位資料長度
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬體資料流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發模式
USART_Init(USART2, &USART_InitStructure); ; //初始化串口
USART_Cmd(USART2, ENABLE); //使能串口
}
//串口2中斷配置
void usart2_NVIC__init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占優先級2級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級2級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開啟中?
}
上位機與單片機之間
上位機與單片機之間通過串口2通訊 ,當上位機向單片機發送命令時,單片機接收到命令執行相應操作,比如上位機發送“ I”,單片機就會向電力表發送相應的查電流的代碼,
串口2中斷服務程式如下:
此處千萬要注意,千萬要注意中斷服務程式的名字不能寫錯,否則就不能進中斷,(當時這個Bug找了好久…想哭 悲傷 哭泣 委屈)
//串口2中斷服務函式
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)//檢測中斷接收標志位是否置1
uctemp=USART_ReceiveData(USART2);
}
電力表與單片機之間
單片機——>電力表
MODBUS_RTU通訊協議補充
電力表提供了RS485通訊介面,采用MODBUS——RTU通訊規約,

例如:主機發送資料幀:讀三相電流值
| 地址 | 命令 | 起始地址(高位在前) | 暫存器數(低位在前) | 校驗碼 |
|---|---|---|---|---|
| 01H | 03H | 00H,45H | 00H,06H | D4H,1DH |
存電流暫存器的起始地址是“00H,45H”(查說明書MODBUS——RTU地址資訊表得,即69),存放三相電流的暫存器一共有六個,所以暫存器數是“00H,06H”,

校驗碼是通過專用計算器算的,
所以定義讀取電壓、電流、功率的陣列如下:
u8 current[8]={0x01,0x03,0x00,0x45,0x00,0x06,0xD4,0x1D};
u8 voltage[8]={0x01,0x03,0x00,0x39,0x00,0x06,0x15,0xC5};
u8 power[8]={0x01,0x03,0x00,0x4B,0x00,0x06,0xB5,0xDE};
串口發送指令補充
//發送一個位元組
void sendByte(USART_TypeDef* USARTx,u8 date)
{
USART_SendData(USARTx, date);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET);
}
//發送兩個位元組
void sendTwoByte(USART_TypeDef* USARTx,u16 date)
{
u8 temp_h,temp_l;
temp_h =(date&0xff00)>>8;
temp_l=(date&0xff);
sendByte(USARTx,temp_h);
sendByte(USARTx,temp_l);
}
//發送四個位元組
void sendFourByte(USART_TypeDef* USARTx,u32 date)
{
u8 temp1,temp2,temp3,temp4;
temp1 =(date&0xff000000)>>24;
temp2=(date&0xff0000)>>16;
temp3=(date&0xff00)>>8;
temp4=(date&0xff);
sendByte(USARTx,temp1);
sendByte(USARTx,temp2);
sendByte(USARTx,temp3);
sendByte(USARTx,temp4);
}
//發送8位陣列
void sendArry(USART_TypeDef* USARTx,u8 *arry,u8 num)
{
u8 i;
for(i=0;i<num;i++)
{
sendByte(USARTx,arry[i]);
}
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
}
//發送字串
void Usart_Sendstr(USART_TypeDef* USARTx,char*str)
{
u8 i=0;
do
{
sendByte(USARTx,str[i]);
i++;
}
while(*(str+i)!='\n');
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
}
單片機接收到命令后,通過串口1向電力表發送相應指令,電力表通過串口1回傳資料,進入串口1的中斷服務子程式,把接收到的資料存在接收快取暫存器里面,具體程式如下:
//串口1中斷服務函式
//USART_RX_BUF[17];接識訓沖,最大17個位元組 , USART_RX_STA;接收狀態標記,記錄接收到第幾個位元組
void USART1_IRQHandler(void)
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷
{
Res =USART_ReceiveData(USART1); //讀取接收到的資料
USART_RX_BUF[USART_RX_STA] = Res;
USART_RX_STA++;
if(USART_RX_STA==17)//回傳的資料一共有17個位元組
{
USART_RX_STA=0;
flag =1;//flag是接收完成標志位
}
}
}
單片機再把回傳的資料發送給上位機,
if(flag)//串口1接收中斷完成
{
for(t=3;t<15;t++)//陣列里的第四個位元組開始是電流值
{
USART_SendData(USART2, USART_RX_BUF[t]);//向串口2發送資料
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待發送結束
}
flag=0;
}
只接A相負載的實驗結果如圖

可見A相的電流值為“32 30 20 C5”,這是一個4個位元組表示的浮點型資料,標準的IEEE-754標準,后續還要對資料進行處理,直接用ASCLL碼表示浮點型,
未完待續,,,,,,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/207787.html
標籤:其他
