NUC140之串口UART

33 篇文章 1 订阅

UART可以说是串行通信用的最多的协议,相对其他协议也比较简单,一般只要设置好比特率,数据位,停止位和校验位即可。下面来看程序。

#include "UART.h"    
#include <stdio.h>
volatile static uint8_t Rx_UART[20] = {0};          //串口存储接收数据数组,加static作为静态全局变量仅能在本文件内部使用
volatile static uint8_t Rx_UART_counter = 0;        //串口存储接收数据数组计数器
volatile static uint8_t UART_one_frame_end;            //串口一帧数据传输结束标志
volatile static uint8_t return_OK_flag = 0;            //判断是否是设置命令标志
volatile static uint8_t verify_data[20] = {0};        //寄存用于校验的值的数组
void UART_callback (uint32_t tempdata);

/**************************************************
 *函数名:    send_to_UART                           *
 *功能:    keil库函数发送UART                    *
 *出口参数:无                                      *
 *入口参数:无                                      *
 *************************************************/
void send_to_UART(const uint8_t *src,uint8_t len)
{
    uint8_t i = 0 ;
    printf("\n");
    for(i=0;i<len;i++)
    {
        printf("%.2X",src[i]);
    }
    printf("\r");
}

/**************************************************
 *函数名:    uint8_t check_ASCII_table             *
 *功能:    ASCII码查表函数                       *
 *出口参数:无                                      *
 *入口参数:无                                      *
 *************************************************/
void initialize_UART_clock (void)
{
    DrvSYS_UnlockProtectedReg ();                         //解锁受保护的系统寄存器
    DrvSYS_SetOscCtrl (E_SYS_XTL12M, 1);   
    DrvSYS_SelectIPClockSource (E_SYS_UART_CLKSRC, 0x00); //设置UART时钟源为外部12MHz晶振
    DrvSYS_SetIPClock (E_SYS_UART0_CLK, 1);                  //使能串口0的时钟
    DrvSYS_LockProtectedReg ();                           //对系统寄存器上锁
}

/**************************************************
 *函数名:    initialize_UART                         *
 *功能:    初始化串口                            *
 *出口参数:无                                      *
 *入口参数:无                                      *
 *************************************************/
void initialize_UART (void)
{
    STR_UART_T sParam;
      sParam.u32BaudRate                = 9600;                      //波特率9600
    sParam.u8cDataBits                = DRVUART_DATABITS_8;          //数据位8位
    sParam.u8cStopBits                = DRVUART_STOPBITS_1;          //停止位1bit
    sParam.u8cParity                  = DRVUART_PARITY_NONE;      //无校验
    sParam.u8cRxTriggerLevel          = DRVUART_FIFO_1BYTES;      //串口中断触发级别1个字节
    DrvUART_Open (UART_PORT0, &sParam);                              //端口0初始化
    delay (100);                                                  //延迟使时钟稳定

    DrvUART_EnableInt(UART_PORT0,         //使能串口0中断
                        DRVUART_RDAINT,    //接收到数据进入中断
                       UART_callback);   //中断回调函数
}

/**************************************************
 *函数名:    UART_callback                         *
 *功能:    串口接收函数                          *
 *出口参数:无                                      *
 *入口参数:有,暂无用                              *
 *************************************************/
void UART_callback (uint32_t tempdata)
{
    uint8_t temp_UART[1] = {0};                            //串口接收临时存储变量数组
    volatile static uint8_t start_flag = 0;                //串口通信开始标志

    DrvUART_Read(UART_PORT0,                            //读取端口0的数据
                 temp_UART,                                //储存于该数组中
                 1);                                    //读取字节数为1

    if (start_flag != 0)                                //通信开始后才进入
    {
        if (temp_UART[0] == 13)                            //如果收到结束标志位(ASCII码13对应CR,结束标志位)
        {
            UART_one_frame_end = 1;                        //表示已经接收到一帧数据,要进行判断
            start_flag = 0;                                //清零等待下一帧的开始
        }
        else 
        {
            Rx_UART[Rx_UART_counter] = temp_UART[0];    //将接收到的字节挨个存储起来
            Rx_UART_counter++;                            
        }    
    }

    if (temp_UART[0] == 10)                                //如果收到起始标志位(ASCII码10对应LF,起始标志位)
    {
        start_flag = 1;                                 //串口通信开始        
    }
    if (UART_one_frame_end == 1)                                             //串口接收到了命令
    {
        if (UART_Rx_verify())                                                 //如果校验结果一致
        {
            UART_Rx_solve();                                                 //接收数据处理函数
              if(return_OK_flag == 1)
            {
                UART_Tx(RX_OK_COMMMAND);                                       //回传收到的数据与检验结果一致(以‘B’开头的设置命令要返回,以'A'开头的查询命令无需返回) 
                return_OK_flag = 0;
            }
        }
        else
        {
            UART_Tx(RX_ERROR_COMMAND);                                       //回传收到的数据与检验结果不一致 
        }
    }
}

/**************************************************
*函数名:  UART_Rx_verify                          *
*功能:       串口接收数据校验函数                   *
*出口参数:为1:接收数据与校验结果一致              *
           为0:接收数据与校验结果不一致          *
*入口参数:无                                      *
***************************************************/
uint8_t UART_Rx_verify (void) 
{
    uint8_t verify_value = 0;                           
    uint8_t verify_value_Rx = 0;                        
    uint8_t i;
    uint8_t temp_data[20] = {0};

    check_ASCII_table((uint8_t *)Rx_UART, (uint8_t *)temp_data, Rx_UART_counter); //收到校验码后先将ASCII码转译为16进制数值后再校验
    combine((uint8_t *)temp_data, (uint8_t *)verify_data, Rx_UART_counter);           //转译后合并
    for (i=0; i<(Rx_UART_counter/2-1); i++)                //和校验,溢出不管,由于收到的最后两个数据是校验值,所以不计入该次计算中
    {
        verify_value *= 3;
        verify_value += verify_data[i];      
    }
    verify_value_Rx = verify_data[Rx_UART_counter/2-1]; //读取发送回来的校验值

    if ((verify_value == verify_value_Rx)&&((Rx_UART_counter%2)==0))     //收到的一定是偶数个字节
    {
        Rx_UART_counter = 0;                            //计数器清零
        return (1);                                        //返回接收数据与校验结果一致,开始判断
    }
    else
    {
        Rx_UART_counter = 0;                            //计数器清零
        UART_one_frame_end = 0;                         //由于不必判断,清除一帧接收完成标志,可以接收下一帧数据
        return (0);                                        //返回接收数据与校验结果不一致,不必判断
    }
}
/**************************************************
 *函数名:    UART_Rx_solve                          *
 *功能:    串口接收数据处理函数                  *
 *出口参数:无                                      *
 *入口参数:无                                      *
 *************************************************/
void UART_Rx_solve(void)
{
    if (Rx_UART[0] == 'B')
    {                                                                       
        return_OK_flag = 1;    
    }
    else
    {
        return_OK_flag = 0;    
    }

    if (verify_data[0] == 0xb1)                                               
    {
        power_value = CHECK_BCD_TABLE(verify_data[2]);                          
        if (power_value > 50)                                                  
        {                                                         
            power_value = 50;    
        }
        else if (power_value < 10)
        {
            power_value = 10;
        }
        SPI_U28_write(power_setup_table[power_value]);                        
        at24c32_write(DEVICE_ADDRESS, POWER_VALUE_HIGH_ADDRESS, POWER_VALUE_LOW_ADDRESS, power_value);
        SPI_U27_write(modulation_setup_table[power_value][modulation_value]); 
    }
    
    else if (verify_data[0] == 0xb2)                                       
    {
        modulation_value = CHECK_BCD_TABLE(verify_data[2]);                 
        if (modulation_value > 99)                                             
        {
            modulation_value = 99;                       
        }
        else if (modulation_value < 30)                                  
        {
            modulation_value = 30;                       
        }
        SPI_U27_write(modulation_setup_table[power_value][modulation_value]);
        at24c32_write(DEVICE_ADDRESS, MODULATION_VALUE_HIGH_ADDRESS, MODULATION_VALUE_LOW_ADDRESS, modulation_value);
    }
                                  
    else if (verify_data[0] == 0xb3)                                  
    {
        if (verify_data[2] == 1)                                  
        {
            radio_main = 1;                                         
        }
        else
        {
            radio_main = 0;                                                
        }
        at24c32_write(DEVICE_ADDRESS, RADIO_MAIN_HIGH_ADDRESS, RADIO_MAIN_LOW_ADDRESS, radio_main);
    }
    
    else if (verify_data[0] == 0xb4)                        
    {
        if (verify_data[2] == 0)                                     
        {
            enable_PTT_limit = 0;                                         
            at24c32_write(DEVICE_ADDRESS, ENABLE_PTT_LIMIT_HIGH_ADDRESS, ENABLE_PTT_LIMIT_LOW_ADDRESS, 0); //存入新的是否使能发定时功能默认值
        }
        else
        {
            enable_PTT_limit = 1;                                         
            at24c32_write(DEVICE_ADDRESS, ENABLE_PTT_LIMIT_HIGH_ADDRESS, ENABLE_PTT_LIMIT_LOW_ADDRESS, 1); //存入新的是否使能发定时功能默认值
            PTT_limit_time = verify_data[2] * 60;                             //发定时时间数据是按档位发过来的
            if (PTT_limit_time > 300)                                      
            {
                PTT_limit_time = 300;
            }
            DrvTIMER_ClearTimerEvent(E_TMR0,0);                                 
            setup_ptt_limit_time (PTT_limit_time);                         
            at24c32_write(DEVICE_ADDRESS, PTT_LIMIT_TIME_HIGH_ADDRESS, PTT_LIMIT_TIME_LOW_ADDRESS, (Rx_UART[2] - 48)); //存入新的发定时时间默认值
        }
    }
    
    else if (verify_data[0] == 0xb5)                                  
    {
        if (verify_data[2] == 0)                                           
        {
            enable_error = 0;                                             
            at24c32_write(DEVICE_ADDRESS, ENABLE_ERROR_HIGH_ADDRESS, ENABLE_ERROR_LOW_ADDRESS, 0); //存入新的是否使能报错关二次默认值
        }
        else
        {
            enable_error = 1;                                               
            at24c32_write(DEVICE_ADDRESS, ENABLE_ERROR_HIGH_ADDRESS, ENABLE_ERROR_LOW_ADDRESS, 1); //存入新的是否使能报错关二次默认值                
        }
    }

    else if (verify_data[0] == 0xb6)                                      
    {
    
        carrier_frequency = CHECK_BCD_TABLE(verify_data[2]) * 10000 + CHECK_BCD_TABLE(verify_data[3]) * 100 + CHECK_BCD_TABLE(verify_data[4]);/

        if (carrier_frequency < 118000)                                        
        {
            carrier_frequency = 118000;
        }
        if (carrier_frequency > 144000)                                         
        {
            carrier_frequency = 144000;
        }
        if ((carrier_frequency%25)==0)                                          
        {
            channel_space = 1;
            DrvGPIO_ClrBit (E_GPC, 5);                                        //PC.5置0
        }
        else                                                                 
        {
            channel_space = 0;    
            DrvGPIO_SetBit (E_GPC, 5);                                        //PC.5置1
        }

        carrier_frequency /= 1000;
        at24c32_write(DEVICE_ADDRESS, CHANNEL_SPACE_HIGH_ADDRESS, CHANNEL_SPACE_LOW_ADDRESS, channel_space);//存入信道间隔新值
        at24c32_write(DEVICE_ADDRESS, FREQUENCY_HIGH_ADDRESS, FREQUENCY_LOW_ADDRESS, carrier_frequency);//存入电台地址新值
    }
    
    else if (verify_data[0] == 0xb7)                                    
    {
        if (verify_data[2] == 0)                                              
        {
            Rx_SQ(0);                                                 
        }
        else
        {
            Rx_SQ(1);                                                     
        }
    }

    else if (verify_data[0] == 0xb8)                                   
    {
        if (verify_data[2] == 0)                                           
        {
            status_register2.status_sample.PC_off = 1; //置位状态标志                                                     
    
        }
        else
        {
            status_register2.status_sample.PC_off = 0; //置位状态标志    
        }
    }

    else if (verify_data[0] == 0xb9)                                        
    {
        error_register1.error_sample_all = 0;                                 
        temperature_error_counter = 0;                                          
        supply_28V_error_counter = 0;                                     
        DISF_solve_counter = 0;                                               
        DIRR_solve_counter = 0;                                             

    else if (verify_data[0] == 0xba)                                  
    {
        if (verify_data[2] == 0)                                            
        {
            PTT_enable = 0; //禁发PTT                                                     
    
        }
        else
        {
            PTT_enable = 1; //允许发PTT    
        } 
    }    
            
    else if (verify_data[0] == 0xa1)                                      
    {
        UART_Tx (DISF_DISR_DISM_VALUE_COMMAND);    
    }
    
    else if (verify_data[0] == 0xa2)                                          
    {
        UART_Tx (READ_ERROR_COMMAND);    
    }
    
    else if (verify_data[0] == 0xa3)                                         
    {
        UART_Tx (READ_TEMPERATURE_COMMAND);    
    }

    else if (verify_data[0] == 0xa6)                                 
    {
        UART_Tx (RECEIVER_AGC_COMMMAND);    
    }
    
    else if (verify_data[0] == 0xa7)                                      
    {
        UART_Tx (READ_ALL_STATUS_COMMMAND);    
    }
        
    UART_one_frame_end = 0;                                                        //清除一帧接收完成标志,可以接收下一帧数据
} 

/**************************************************
 *函数名:    UART_Tx                                *
 *功能:    串口发送函数                          *
 *出口参数:无                                      *
 *入口参数:发送命令类型                          *
 *************************************************/
void UART_Tx (uint8_t command)
{
    uint8_t temp_UART[1] = {0};               //串口发送临时存储变量数组
    uint8_t Tx_UART[20] = {0};               //串口发送存储变量数组
    uint8_t temp_data[20] = {0};
    uint8_t temp_data_verify[20] = {0};
    uint8_t Tx_UART_counter = 0;           //串口发送存储变量数组计数器
    uint8_t verify_value = 0;              //校验值
    uint8_t verify_value_first;            //校验值第一位
    uint8_t verify_value_second;           //校验值第二位

    uint8_t i;
    uint8_t j;

    Tx_UART[0] = 10;                               //无论哪一条命令一定先发起始标志'LF' ASCII对应10
    Tx_UART[1] = 'A';                              //无论哪一条命令命令格式第一个都是字符'A'
                                                   //这两句放前面可以减少过多的重复代码
    if (command == DISF_DISR_DISM_VALUE_COMMAND)     
    {
        Tx_UART[2] = '1';                               
        Tx_UART[3] = '0';                               //数据长度为3, 分两个字节表示
        Tx_UART[4] = '3';                            
        Tx_UART[5] = DISF_value / 10 + '0';               //加上'0',即转换成字符型,看ASCII码表就明白了(十位不可能超过9,没有大于160的数据)
        Tx_UART[6] = DISF_value % 10 + '0';             

        Tx_UART[7] = DISR_value / 10 + '0';        
        Tx_UART[8] = DISR_value % 10 + '0';            

        Tx_UART[9] = DISM_value / 10 + '0';            
        Tx_UART[10] = DISM_value % 10 + '0';          
        Tx_UART_counter = 10;
    }

    else if (command == READ_ERROR_COMMAND)                          //如果是要读取总的错误信号
    {
        Tx_UART[2] = '2';                                          //发送总的错误信号
        Tx_UART[3] = '0';                                          //数据长度为2
        Tx_UART[4] = '2';                                                      
        Tx_UART[5] = (error_register1.error_sample_all & 0xf0)>>4;  //总的错误信号寄存器1高4位
        NUMBER_TO_BCD(Tx_UART[5]);
        Tx_UART[6] = error_register1.error_sample_all & 0x0f;       //总的错误信号寄存器1低4位
        NUMBER_TO_BCD(Tx_UART[6]);
        Tx_UART[7] = (status_register2.status_sample_all & 0xf0)>>4;//总的错误信号寄存器2高4位
        NUMBER_TO_BCD(Tx_UART[7]);
        Tx_UART[8] = status_register2.status_sample_all & 0x0f;     //总的错误信号寄存器2低4位
        NUMBER_TO_BCD(Tx_UART[8]);
        Tx_UART_counter = 8;
    }

    else if (command == READ_TEMPERATURE_COMMAND)       //如果是要读取温度的命令
    {
        Tx_UART[2] = '3';                               //发送温度值
        Tx_UART[3] = '0';                               //数据长度为1    
        Tx_UART[4] = '1';                                
        Tx_UART[5] = temperature_value / 10 + '0';       //取温度值的十位值
        Tx_UART[6] = temperature_value % 10 + '0';       //取温度值的个位值
        Tx_UART_counter = 6;    
    }

    else if (command == RX_ERROR_COMMAND)      //如果是要发送接收到的数据与校验码不一致
    {
        Tx_UART[2] = '4';                      
        Tx_UART[3] = '0';                       //数据长度为0
        Tx_UART[4] = '0';
        Tx_UART_counter = 4;
    }

    else if (command == RX_OK_COMMMAND)           //如果是要发送接收到的数据与校验码一致
    {
        Tx_UART[2] = '5';
        Tx_UART[3] = '0';                       //数据长度为0
        Tx_UART[4] = '0';
        Tx_UART_counter = 4;                  
    }

    else if (command == RECEIVER_AGC_COMMMAND)
    {
        Tx_UART[2] = '6';
        Tx_UART[3] = '0';                       //数据长度为1    
        Tx_UART[4] = '1';                                        
        Tx_UART[5] = '0';
        Tx_UART[6] = Rx_AGC() + '0';
        Tx_UART_counter = 6;
    }

    else if (command == READ_ALL_STATUS_COMMMAND) 
    {
        Tx_UART[2] = '7';
        Tx_UART[3] = '0';                             //数据长度为
        Tx_UART[4] = '4';

        Tx_UART[5] = (error_register1.error_sample_all & 0xf0)>>4;  
        NUMBER_TO_BCD(Tx_UART[5]);
        Tx_UART[6] = error_register1.error_sample_all & 0x0f;       
        NUMBER_TO_BCD(Tx_UART[6]);
        Tx_UART[7] = (status_register2.status_sample_all & 0xf0)>>4;
        NUMBER_TO_BCD(Tx_UART[7]);
        Tx_UART[8] = status_register2.status_sample_all & 0x0f;     
        NUMBER_TO_BCD(Tx_UART[8]);

        Tx_UART[9] = temperature_value / 10 + '0';      
        Tx_UART[10] = temperature_value % 10 + '0';                                      
        
        Tx_UART[11] = '0';
        Tx_UART[12] = Rx_AGC() + '0';
        
        Tx_UART_counter = 12;
    }

    check_ASCII_table((uint8_t *)(Tx_UART+1), (uint8_t *)temp_data, Tx_UART_counter); //收到校验码后先将ASCII码转译为16进制数值后再校验
    combine((uint8_t *)temp_data, (uint8_t *)temp_data_verify, Tx_UART_counter);     
    for (i=0; i<(Tx_UART_counter/2); i++)     //计算校验值,溢出不管,注意条件是<=
    {
        verify_value *= 3;
        verify_value += temp_data_verify[i]; //第0个元素是起始标志,不校验
    }
    verify_value_first = verify_value / 16;     //取校验值的十位数,按16进制
       verify_value_second = verify_value % 16; //取校验值的个位数,按16进制
    NUMBER_TO_BCD(verify_value_first);
    NUMBER_TO_BCD(verify_value_second);

    Tx_UART_counter += 2;             //加2准备存储校验值,校验值占2位
    Tx_UART[Tx_UART_counter - 1] = verify_value_first; //存储校验值第一位(十位)
    Tx_UART[Tx_UART_counter] = verify_value_second;    //存储校验值第二位(个位)
    Tx_UART_counter += 1;             //加1准备存储结束标志
    Tx_UART[Tx_UART_counter] = 13;                     //存储结束标志'CR'对应ASCII码13

    for (j=0; j<=Tx_UART_counter; j++)
    {
        temp_UART[0] = Tx_UART[j];
        DrvUART_Write(UART_PORT0,             //UART端口0
                        (uint8_t *)temp_UART,     //要发送的数据储存数组地址
                        1);                     //发送字节数
    }
}

头文件如下

#ifndef UART_h
#define UART_h

#include "stdint.h"
#include "DrvUART.h"
#include "SPI_U27_U28.h"
#include "I2C_remote.h"    
#include "at24c32.h"
#include "timer.h"
#include "delay.h"
#include "common_functions.h"
#include "I2C_remote.h"

#define DISF_DISR_DISM_VALUE_COMMAND 0x01  
#define READ_ERROR_COMMAND           0x02  //读取总的错误信号命令
#define READ_TEMPERATURE_COMMAND     0x03  //读取温度状态命令
#define RX_ERROR_COMMAND             0x04  //串口接收数据与校验值不一致
#define RX_OK_COMMMAND               0x05  //串口接收数据与校验值一致
#define RECEIVER_AGC_COMMMAND        0x06 
#define READ_ALL_STATUS_COMMMAND     0x07  

extern void initialize_UART_clock (void) ; //初始化串口时钟
extern void initialize_UART (void);        //初始化UART
extern void UART_Tx (uint8_t command);     //给前面板发送状态,参数对应发送的状态类型
extern uint8_t UART_Rx_verify (void);      //串口接收到数据校验函数
extern void UART_Rx_solve(void);           //串口接收数据处理函数
#endif 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值