找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3226|回復(fù): 0
收起左側(cè)

STM32單片機(jī)+GM65二維碼識(shí)別源程序

[復(fù)制鏈接]
ID:949309 發(fā)表于 2022-4-28 15:59 | 顯示全部樓層 |閱讀模式
#include "delay.h"
#include "usart3.h"
#include "stdarg.h"                  
#include "stdio.h"                  
#include "string.h"         
#include "timer.h"
#include "lcd.h"
#include "usart.h"   

//串口接收緩存區(qū)         
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN];                                 //接收緩沖,最大USART3_MAX_RECV_LEN個(gè)字節(jié).
u8  USART3_TX_BUF[USART3_MAX_SEND_LEN];                         //發(fā)送緩沖,最大USART3_MAX_SEND_LEN字節(jié)

//通過判斷接收連續(xù)2個(gè)字符之間的時(shí)間差不大于10ms來決定是不是一次連續(xù)的數(shù)據(jù).
//如果2個(gè)字符接收間隔超過10ms,則認(rèn)為不是1次連續(xù)數(shù)據(jù).也就是超過10ms沒有接收到
//任何數(shù)據(jù),則表示此次接收完畢.
//接收到的數(shù)據(jù)狀態(tài)
//[15]:0,沒有接收到數(shù)據(jù);1,接收到了一批數(shù)據(jù).
//[14:0]:接收到的數(shù)據(jù)長度
vu16 USART3_RX_STA=0;           
        u16 i;
        u16 check;
        u8 uart3_len=0; //數(shù)據(jù)長度,uart3_len+1加上幀尾
        u8 x=0;
        u8 RxCounter1=0;
        u8 RxBuffer1[20]={0};
    u8 RxState = 0;        

//USART1 全局中斷服務(wù)函數(shù)


//初始化IO 串口3
//pclk1:PCLK1時(shí)鐘頻率(Mhz)
//bound:波特率         
void usart3_init(u32 bound)
{  

        NVIC_InitTypeDef NVIC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);        // GPIOB時(shí)鐘
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3時(shí)鐘使能

         USART_DeInit(USART3);  //復(fù)位串口3
                 //USART3_TX   PB10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //復(fù)用推挽輸出
  GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10

    //USART3_RX          PB11
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
  GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11
        
        USART_InitStructure.USART_BaudRate = bound;//波特率一般設(shè)置為9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗(yàn)位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收發(fā)模式

        USART_Init(USART3, &USART_InitStructure); //初始化串口        3


        USART_Cmd(USART3, ENABLE);                    //使能串口
        
        //使能接收中斷
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//開啟中斷   
        
        //設(shè)置中斷優(yōu)先級(jí)
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//搶占優(yōu)先級(jí)3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子優(yōu)先級(jí)3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根據(jù)指定的參數(shù)初始化VIC寄存器
        
        
        TIM7_Int_Init(99,7199);                //10ms中斷
        USART3_RX_STA=0;                //清零
        TIM_Cmd(TIM7,DISABLE);                        //關(guān)閉定時(shí)器7

}




unsigned short CRC16_XMODEM(unsigned char *puchMsg, unsigned int usDataLen)
{
                unsigned short wCRCin = 0x0000;
                unsigned short wCPoly= 0x1021;
                unsigned char wChar = 0;
                while (usDataLen--)
                {
                        wChar = *(puchMsg++);//4,1 3,2 3,3, 1,4 1,5
                        wCRCin ^=(wChar << 8);
                                
                        for( i = 0; i< 8; i++)
                   {        
                                if(wCRCin & 0x8000)
                                {
                                   wCRCin =(wCRCin << 1) ^ wCPoly;
                                }
                                else
                                {
                                    wCRCin = wCRCin << 1;
                                }

                        
                   }
       }
                        return(wCRCin);   
}

void USART3_IRQHandler(void)                     
{

               


                if( USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)             //接收中斷  
                {
                                USART_ClearITPendingBit(USART3,USART_IT_RXNE);   //清除中斷標(biāo)志
                                RxBuffer1[RxCounter1++] = USART_ReceiveData(USART3);
                        

                }


               
                if(RxBuffer1[RxCounter1-1]==13) //0x0D
                {
                        uart3_len=RxCounter1-1;
               
                        check=CRC16_XMODEM(&RxBuffer1[RxCounter1],uart3_len+1);   //校驗(yàn)和(crc)
                        if(((check&0x00ff)==RxBuffer1[uart3_len+1])&&(((check>>8)&0x00ff)==RxBuffer1[uart3_len+1]))
                        {
                                RxState=1;
                                                        
                        }
        
                        
                }
               
               
               
               
if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET) //判斷中斷是否溢出
    {
      USART_ClearFlag(USART3,USART_FLAG_ORE);
      USART_ReceiveData(USART3);
    }
        
        if(RxState)
        {
                for(x=0;x<uart3_len+1;x++)
                {USART_SendData(USART1,RxBuffer1[x]);
                delay_ms(10);}

                RxState=0;
                RxCounter1=0;
               
        }
               
               
               
               
}


//串口3,printf 函數(shù)
//確保一次發(fā)送數(shù)據(jù)不超過USART3_MAX_SEND_LEN字節(jié)
//void u3_printf(char* fmt,...)  
//{  
//        u16 i,j;
//        va_list ap;
//        va_start(ap,fmt);
//        vsprintf((char*)USART3_TX_BUF,fmt,ap);
//        va_end(ap);
//        i=strlen((const char*)USART3_TX_BUF);                //此次發(fā)送數(shù)據(jù)的長度
//        for(j=0;j<i;j++)                                                        //循環(huán)發(fā)送數(shù)據(jù)
//        {
//          while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循環(huán)發(fā)送,直到發(fā)送完畢   
//                USART_SendData(USART3,USART3_TX_BUF[j]);
//        }
//}


掃描過后,模塊的串口通訊參數(shù):波特率 9600bps,無校驗(yàn),8 位數(shù)據(jù)位,1 位停止位,無流控。
改為串口后,所有的數(shù)據(jù)都由串口輸出,也可以直接發(fā)送命令控制模塊

對(duì)模塊的標(biāo)志位進(jìn)行讀操作:
發(fā)送命令格式:
{Head1} {Types} {Lens} {Address} {Datas} {CRC}
Head1 :0x7E 0x00(2 bytes)
Types    :0x07(1 byte)
Lens    :0x01(1 byte)
Address :0x0000~0x00FF(2 bytes),表示要讀取的標(biāo)志位的起始地址。
Datas    :0x00~0xFF(1 byte),表示要連續(xù)讀取的標(biāo)志位的字節(jié)數(shù),0x00 表示 256 個(gè)字節(jié)。
CRC    :CRC_CCITT 校驗(yàn)值(2 bytes)。計(jì)算的范圍:Types、Lens、Address、Datas。
計(jì)算的方法為 CRC_CCITT,特征多項(xiàng)式:X16+X12+X5+1,多項(xiàng)式系數(shù)為 0x1021,
初始值為全 0,對(duì)于單個(gè)字節(jié)來說最高位先計(jì)算,不需要取反直接輸出。
注:當(dāng)用戶不需要 CRC 校驗(yàn)功能時(shí),可在 CRC 字節(jié)處填寫 0xAB 0xCD,免校驗(yàn)。

接收到數(shù)據(jù)格式:
1:如果模塊成功數(shù)據(jù)并且成功返回
{Head2} {Types} {Lens} {Datas} {CRC}
Head2 :0x02 0x00
Types    :0x00(讀成功)
Lens    :表示上傳的 Datas 的字節(jié)個(gè)數(shù),0x00 表示 256 個(gè)
Datas    :0x00~0xFF,表示讀上來的數(shù)據(jù)
CRC   : CRC_CCITT 校 驗(yàn) 值 。 計(jì)算的范圍:Types、Lens、Datas。計(jì)算的方法為 CRC_CCITT,特征多項(xiàng)式:X16+X12+X5+1,多項(xiàng)式系數(shù)為 0x1021,初
始值為全 0,對(duì)于單個(gè)字節(jié)來說最高位先計(jì)算,不需要取反直接輸出。
注:當(dāng)用戶不需要 CRC 校驗(yàn)功能時(shí),可在 CRC 字節(jié)處填寫 0xAB 0xCD,免校驗(yàn)。


2: 下發(fā) CRC 校驗(yàn)失敗
無回應(yīng)命令

3:未知命令應(yīng)答
無回應(yīng)命令
示例:(供參考)

CRC  C 參考代碼:
unsigned int crc_cal_by_bit(unsigned char* ptr, unsigned int len)
{
unsigned int crc = 0;
while(len-- != 0)
{
for(unsigned char i = 0x80; i != 0; i /= 2)
{
crc *= 2;
if((crc&0x10000) !=0) //上一位 CRC 乘 2 后,若首位是 1,則除以 0x11021
crc ^= 0x11021;
if((*ptr&i) != 0) //如果本位是 1,那么 CRC = 上一位的 CRC + 本位/CRC_CCITT
crc ^= 0x1021;
}
ptr++;
}
return crc;
}
注:當(dāng)用戶不需要 CRC 校驗(yàn)功能時(shí),可在 CRC 字節(jié)處填寫 0xAB 0xCD,免校驗(yàn)。

示例:
對(duì)標(biāo)志位中地址為 0x000A 的 1 個(gè)地址進(jìn)行讀操作
1:讀成功并返回?cái)?shù)據(jù),返回的數(shù)據(jù)為 0x3E
輸入:0x7E 0x00 0x07 0x01 0x00 0x0A 0x01 0xEE 0x8A
返回:0x02 0x00 0x00 0x01 0x3E 0xE4 0xAC
2:下發(fā)的 CRC 錯(cuò)誤
輸入:0x7E 0x00 0x07 0x01 0x00 0x0A 0x01 0x11 0x22
返回:無
3:當(dāng)發(fā)送的指令長度不夠或發(fā)送 0x7e 0x00 后等待時(shí)間超過 400ms 時(shí),當(dāng)成未知命令處理
輸入:0x7E 0x00 0x07 0x01 0x00 0x0A 0x01
返回:無



對(duì)模塊標(biāo)志位進(jìn)行寫操作:
發(fā)送命令格式:
{Head1} {Types} {Lens} {Address} {Datas} {CRC}
Head1 :0x7E 0x00(2 bytes)
Types    :0x08(1 byte)
Lens    :0x00~0xFF(1 byte),表示該命令中 Datas 字段的字節(jié)數(shù),同時(shí)也表示要進(jìn)行連續(xù)
寫操作的次數(shù),而 0x00 表示有 256 個(gè)字節(jié)
Address :0x0000~0xFFFF(2 bytes),表示要寫入的標(biāo)志位的起始地址
Datas    :0x00~0xFF(1~256 bytes),表示寫入標(biāo)志位的數(shù)據(jù)
CRC    :CRC_CCITT 校驗(yàn)值(2 bytes)。計(jì)算的范圍:Types、Lens、Address、Datas  
注:當(dāng)用戶不需要 CRC 校驗(yàn)功能時(shí),可在 CRC 字節(jié)處填寫 0xAB 0xCD,免校驗(yàn)。


返回?cái)?shù)據(jù)格式:
1:寫標(biāo)志位成功
{Head2} {Types} {Lens} {Datas} {CRC}
Head2 :0x02 0x00
Types    :0x00(寫成功)
Lens    :0x01
Datas    :0x00
CRC    :CRC_CCITT  

2:下發(fā) CRC 校驗(yàn)失敗
無回應(yīng)命令

3:未知命令應(yīng)答
無回應(yīng)命令


示例:
向地址為 0x000A 的標(biāo)志位寫入 0x3E
1: 設(shè)置成功
輸入:0x7E 0x00 0x08 0x01 0x00 0x0A 0x3E 0x4C 0xCF
返回:0x02 0x00 0x00 0x01 0x00 0x33 0x31

2: 下發(fā)的 CRC 錯(cuò)誤
輸入:0x7E 0x00 0x08 0x01 0x00 0x0A 0x3E 0x11 0x22
返回:無

3: 當(dāng)發(fā)送的指令長度不夠或發(fā)送 0x7e 0x00 后等待時(shí)間超過 400ms 時(shí),當(dāng)成未知命令處理
輸入:0x7E 0x00 0x08 0x01 0x00 0x0A 0x3E
返回:無



   標(biāo)志位保存到 EEPROM 指令

若要將設(shè)備標(biāo)志位的內(nèi)容保存到外掛的 EERPOM 中則需要發(fā)送保存命令。
數(shù)據(jù)發(fā)送命令格式:
{Head1} {Types} {Lens} {Address} {Datas} {CRC}
Head1 :0x7E 0x00
Types    :0x09
Lens    :0x01
Address :0x0000
Datas    :0x00
CRC    :CRC_CCITT 校驗(yàn)值(0xDE 0xC8)

接收數(shù)據(jù)格式:
1:保存成功
{Head2} {Types} {Lens} {Datas} {CRC}
Head2 :0x02 0x00
Types    :0x00(寫成功)
Lens    :0x01
Datas    :0x00
CRC    :CRC_CCITT 校驗(yàn)值(0x33 0x31)
2:下發(fā) CRC 校驗(yàn)失敗
無回應(yīng)命令

3:未知命令應(yīng)答
無回應(yīng)命令

部分串口命令示例:
1:觸發(fā)掃描串口指令為:7E 00 08 01 00 02 01 AB CD;識(shí)讀模塊收到觸發(fā)指令后,會(huì)先輸出七個(gè)字節(jié)的回應(yīng)信息并同步啟動(dòng)掃描(回應(yīng)信息內(nèi)容:02 00 00 01 00 33 31)
2:設(shè)置模塊為命令觸發(fā)模式,照明燈常亮,普通瞄準(zhǔn),啟動(dòng)靜音,開啟解碼成功LED提示
發(fā)送格式:7E 00 08 01 00 00 99 AB CD   
接收成功后返回: 02 00 01 00 33 31
3:設(shè)置模塊為感應(yīng)模式,照明燈關(guān)閉,瞄準(zhǔn)常亮,關(guān)閉靜音,關(guān)閉解碼成功LED提示
發(fā)送格式:7E 00 08 01 00 00 63 AB CD   
接收成功后返回: 02 00 01 00 33 31
4:從標(biāo)志位0X0002中讀取數(shù)據(jù),判斷是否輸出解碼狀態(tài)提示符
發(fā)送格式:7E 00 07 01 00 02 01 AB CD
接收成功后返回;02 00 00 01 40 AB CD

Keil代碼等資料下載: GM65.7z (1.34 MB, 下載次數(shù): 57)

評(píng)分

參與人數(shù) 1黑幣 +40 收起 理由
admin + 40 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表