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