概述
1、I2C,
I2C每次只能读写一个字节,读写过程就是操作相关寄存器,读取或者填充数据到外部缓冲区中;
EEPROM使用的I2C来完成读写;
2、GPIO
包含多个端口,每个端口包含引脚;
每个引脚,可以配置:输入还是输出,方向,开漏模式;
使用GPIO的模块有:AD采集,BEEP控制,LED控制,VALVE控制,PUMP控制,PWM控制,FAN控制;
附:8种工作模式定义;
(1)GPIO_Mode_AIN 模拟输入
(2)GPIO_Mode_IN_FLOATING 浮空输入
(3)GPIO_Mode_IPD 下拉输入
(4)GPIO_Mode_IPU 上拉输入
(5)GPIO_Mode_Out_OD 开漏输出
(6)GPIO_Mode_Out_PP 推挽输出
(7)GPIO_Mode_AF_OD 复用开漏输出
(8)GPIO_Mode_AF_PP 复用推挽输出
Timer
#include "deftype.h"
#include "lpc17xx.h"
#include "timer.h"
#include "stdlib.h"
/***********************************************************************/
//函数声明
timer_ch* seek_timer_ch(uint32 ucTimerCh);
/***********************************************************************/
//宏定义
//定时器时钟定义
#define TIMER_PERI_CLOCK (18000000) /*!< 72MHz/4=18MHz */
//变量定义
timer_ch timer_num = {0};//定时器链表头
timer_ch_tail timer_num_tail = {0};//定时器链表尾
int32 timer_init(void)
{
LPC_SC->PCONP |= (1 << 1);
LPC_TIM0->MR0 = (TIMER_PERI_CLOCK/1000 * TIMER0_INT_VALUE) - 1;
LPC_TIM0->MCR = 0x03; /*使能中断,并且中断后复位计数器*/
NVIC_EnableIRQ(TIMER0_IRQn);
LPC_TIM0->TCR = 0x01;
timer_num.next = NULL;
timer_num.timer_ch = DELAY_10MS;
timer_num.timer_count = 0;
timer_num.timer_data = TIMER0_DELAY_10MS;
timer_num.phandle = NULL;
timer_num_tail.timer_tail = &timer_num;
timer_num_tail.cnt = 0;
return EXIT_SUCCESS;
}
void disable_timer(void)
{
LPC_TIM0->TCR = 0x00;
}
int32 check_timer_delay( uint8 ucTimerCh)
{
timer_ch* timer_ch_return = NULL;
//查询定时器变量
timer_ch_return = seek_timer_ch(ucTimerCh);
//没有找到
if(NULL == timer_ch_return)
{
return NONE_SCHEDULE;
}
//找到处理
else
{
//定时到
if(timer_ch_return->timer_count >= timer_ch_return->timer_data)
{
//清零计数
timer_ch_return->timer_count = 0;
//调用处理函数
if(NULL != timer_ch_return->phandle)
{
timer_ch_return->phandle();
}
return MEET_SCHEDULE;
}
//定时未到
else
{
return NONE_SCHEDULE;
}
}
}
uint32 get_timer_ch_num(void)
{
return timer_num_tail.cnt;
}
void timer_ch_insert(timer_ch_tail *tail,timer_ch* var,uint32 ucTimerCh,uint32 ucTimerDat,pfunction pfunchandle)
{
if(tail->timer_tail != NULL)
{
//链表尾插入定时变量
tail->timer_tail->next = var;
tail->timer_tail->next->timer_ch = ucTimerCh;
tail->timer_tail->next->timer_data = ucTimerDat;
tail->timer_tail->next->timer_count = 0;
tail->timer_tail->next->phandle = pfunchandle;
tail->timer_tail->next->next = NULL;
tail->cnt++;
}
}
int32 insert_timer_ch(uint32 ucTimerCh,uint32 ucTimerDat,pfunction pfunchandle)
{
timer_ch* ptimer_ch = NULL;
ptimer_ch = malloc(sizeof(timer_ch));
//内存分配判断
if(ptimer_ch == NULL)
{
return EXIT_FAILURE;
}
//链表尾插入定时变量
timer_ch_insert(&timer_num_tail,ptimer_ch,ucTimerCh,ucTimerDat,pfunchandle);
//更新链表尾指针
timer_num_tail.timer_tail = ptimer_ch;
return EXIT_SUCCESS;
}
timer_ch* seek_timer_ch(uint32 ucTimerCh)
{
timer_ch* timer_ch_return = NULL;
timer_ch_return = &timer_num;
for(;timer_ch_return != NULL;timer_ch_return = timer_ch_return->next)
{
if(ucTimerCh == timer_ch_return->timer_ch)
{
return timer_ch_return;
}
}
return (timer_ch*)0;
}
void set_timer_counter(uint32 ucTimerCh, uint32 unCnt)
{
timer_ch* timer_ch_return = NULL;
timer_ch_return = seek_timer_ch(ucTimerCh);
timer_ch_return->timer_count = unCnt;
}
uint32 get_timer_counter(uint32 ucTimerCh)
{
timer_ch* timer_ch_return = NULL;
timer_ch_return = seek_timer_ch(ucTimerCh);
return timer_ch_return->timer_count;
}
void set_timer_delay(uint32 ucTimerCh, uint32 unDelay)
{
timer_ch* timer_ch_return = NULL;
timer_ch_return = seek_timer_ch(ucTimerCh);
timer_ch_return->timer_data = unDelay;
}
void TIMER0_IRQHandler(void)
{
timer_ch* timer_ch_return = NULL;
//清除定时器中断标志
LPC_TIM0->IR = 0x01;
//更新定时值
timer_ch_return = &timer_num;
for(;timer_ch_return != NULL;timer_ch_return = timer_ch_return->next)
{
timer_ch_return->timer_count++;
}
}
Main
/************************************************************/
//app实现
int main(void)
{
uint8 i = 0;
//上电初始化
//初始化定时器
timer_init();
led_init(leds,LED_NUM);
//插入led_state定时器变量
insert_timer_ch(LED_STATE_DELAY_LOCOAL,TIMER0_DELAY_200MS,led_state_toggle);
pcb_version_init(versions,VER_NUM);
com_type_init(com_type,COM_TYPE_NUM);
com_port_init(DEBUGPORT,COMMPORT);
//串口初始化
uart_init(UART0_PORT_NUM,115200,160,DATA_BITS_8,STOP_BITS_1,PARITY_NONE);
uart_init(UART1_PORT_NUM,115200,512,DATA_BITS_8,STOP_BITS_1,PARITY_NONE);
//初始化adc
adc_init(AD_CH(0));//正压
adc_init(AD_CH(1));//负压
adc_init(AD_CH(2));//鞘流压
//fpga初始化
fpga_init();
//插入定时器变量
insert_timer_ch(FPGA_CONF_DONE_DELAY_LOCOAL,TIMER0_DELAY_200MS,NULL);
//等待fpga初始化完成
wait_fpga_conf_done();
//初始化can,设置报文滤波的发送节点和接受节点
can_init(CAN1,500000,CAN_MAIN_ID,CAN_LOCAL_ID);
//插入can连接状态延时变量
insert_timer_ch(PRINT_CAN_STATE_DELAY_LOCOAL,TIMER0_DELAY_50MS,can_con_state_process);
//温控通道初始化
pwm_port_init(pwms,PWM_PERIOD_CNT,pwn_drive_active,pwm_channel,PWM_NUM);
//上电信息输出
put_string("\r\n\r\nDriverBoard power on. PCB Version:");
put_dec(get_pcb_version(), NULL);
if(get_comm_port_type() == COMM_TYPE_CAN)
{
put_string(", CAN communication.\r\n");
}
else
{
put_string(", UART communication.\r\n");
}
put_string("Build Date:");
put_string(__DATE__);
put_string(", Time:");
put_string(__TIME__);
put_string(".\r\n");
//关闭所有泵
if(0 > set_pump_state(ALL_PUMP, TURN_OFF_PUMP,PUMP_DRIVE))
{
exit_main_func("E:turn off all pump error!", __FILE__, __LINE__);
}
//关闭所有阀
if(0 > set_valve_state(ALL_VALVE, TURN_OFF_VALVE))
{
exit_main_func("E:turn off all valve error!", __FILE__, __LINE__);
}
//初始化时序包相关数据结构
init_timeseq_struct();
//插入定时器变量
//用于打印时序执行时间
insert_timer_ch(PRINT_TIMESEQ_EXEC_TIME_DELAY_LOCOAL,TIMER0_DELAY_1MS,NULL);
//用于时序包调度
insert_timer_ch(TIMESEQ_DELAY_LOCOAL,TIMER0_DELAY_10MS,timeseq_control);
//初始化电机结构体
if(0 > init_motor_struct())
{
exit_main_func("E:Init motor struct error!", __FILE__, __LINE__);
}
else
{
//插入电机动作延时定时器变量
insert_timer_ch(MOTOR_DELAY_LOCOAL,TIMER0_DELAY_10MS,check_motor_action_delay);
}
//初始化采样组件结构体
if(0 > init_sample_struct())
{
exit_main_func("E:Init sample struct error!", __FILE__, __LINE__);
}
else
{
insert_timer_ch(SAMPLE_DELAY_LOCOAL,TIMER0_DELAY_10MS,check_sample_action_delay);
}
//初始化压力运行相关数据结构
if(0 > init_pressure_struct(pdefault_pressure_cfg))
{
exit_main_func("E:Init pressure struct error!", __FILE__, __LINE__);
}
else
{
//插入压力监控定时器变量
insert_timer_ch(MONITOR_PRESSURE_DELAY_LOCOAL,TIMER0_DELAY_10MS,monitor_pressure_process);
//插入建压延时
insert_timer_ch(BUILD_PRESSURE_DELAY_LOCOAL,TIMER0_DELAY_10MS,pressure_process);
}
//初始化试剂相关数据结构
if(0 > init_reagent_struct(REAGENT_CH_NUM,preagent_default_ch_cfg))
{
exit_main_func("E:Init reagent struct error!", __FILE__, __LINE__);
}
else
{
//插入试剂检测延时
insert_timer_ch(REAGENT_DELAY_LOCOAL,TIMER0_DELAY_1MS,reagent_process);
//插入开关检测延时
insert_timer_ch(SWITCH_DELAY_LOCOAL,TIMER0_DELAY_1000MS,switch_process);
}
//初始化温度控制相关数据结构
if(0 > init_temp_struct(TEMP_CH_NUM,pwn_drive_active,pdefault_temp_ctl_cfg))
{
exit_main_func("E:Init temp struct error!", __FILE__, __LINE__);
}
else
{
//插入温度控制延时变量
//insert_timer_ch(TEMP_DELAY_LOCOAL,TIMER0_DELAY_1000MS,temperature_process);
insert_timer_ch(TEMP_DELAY_LOCOAL,TIMER0_DELAY_1000MS,temperature_process);
}
//led亮,进入主循环
led_state_on();
led_flash_off();
put_string("Power on ok, enter main loop.\r\n");
//插入MCU复位延时变量
insert_timer_ch(MCU_RESET_DELAY_LOCOAL,TIMER0_DELAY_500MS,NULL);
while(1)
{
for(i = 1;i <= 14;i++)
{
check_timer_delay(i);
}
//电机控制
if(0 > motor_process())
{
put_string("E:Motor process error!\r\n");
}
//采样组件控制
if(0 > sample_process())
{
put_string("E:Sample process error!\r\n");
}
//通信协议
if(0 > protocol_process())
{
put_string("E:Protocol process error!\r\n");
}
}
}
AD
void start_ad_convert(uint8 ad_ch)
{
volatile uint32 unused = 0;
unused = LPC_ADC->ADGDR; //清除全局数据寄存器转换完成标志
LPC_ADC->ADCR &= 0xf8ffffff;//停止转换
LPC_ADC->ADCR &= 0xffffff00;//通道号复位
LPC_ADC->ADCR |= AD_CH_SEL(ad_ch);//选择AD通道
LPC_ADC->ADCR |= AD_START(1);//立即启动转换
}
uint16 get_ad_value(uint8 ad_ch)
{
uint16 ad_value = 0x0000;
uint32 ad_adgdr = 0;
uint32 i = 0;
if(ad_ch > 7)
{
return AD_CONVERT_ERR;
}
//启动转换
start_ad_convert(ad_ch);
//等待转换完成
while(1)
{
ad_adgdr = LPC_ADC->ADGDR;//查询全局数据寄存器
if(AD_CONVERT_DONE == (ad_adgdr & AD_CONVERT_DONE))//判断AD转换是否完成
{
if(((uint8)(ad_adgdr>>24) & 0x07) == ad_ch)//判断是否是指定通道的AD
{
ad_value = (uint16)(ad_adgdr>>4) & 0x0fff;
}
else
{
ad_value = AD_CONVERT_ERR;
}
LPC_ADC->ADCR &= 0xf8ffffff;//停止转换
i = 0;
break;
}
i++;
if(720000 < i)//10ms
{
ad_value = AD_CONVERT_ERR;
i = 0;
break;
}
}
return ad_value;
}
void adc_init(uint8 ad_ch)
{
io_st io_to_ad[8] = {\
{GPIO_PORT(0),GPIO_PIN(23),PIN_FUNC(1),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.0
{GPIO_PORT(0),GPIO_PIN(24),PIN_FUNC(1),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.1
{GPIO_PORT(0),GPIO_PIN(25),PIN_FUNC(1),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.2
{GPIO_PORT(0),GPIO_PIN(26),PIN_FUNC(1),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.3
{GPIO_PORT(1),GPIO_PIN(30),PIN_FUNC(3),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.4
{GPIO_PORT(1),GPIO_PIN(31),PIN_FUNC(3),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.5
{GPIO_PORT(0),GPIO_PIN(3), PIN_FUNC(2),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW},//AD0.6
{GPIO_PORT(0),GPIO_PIN(2), PIN_FUNC(2),PIN_MODE_INACTIVE,PIN_OD_DISABLE,GPIO_INPUT,GPIO_STATE_LOW} //AD0.7
};
//使能ADC
LPC_SC->PCONP |= (0x01<<12);
//ADC时钟源选择
//默认值CCLK/4
//配置IO为ADC功能
set_gpio_func(io_to_ad[ad_ch].port,io_to_ad[ad_ch].pin,io_to_ad[ad_ch].func);
set_gpio_mode(io_to_ad[ad_ch].port,io_to_ad[ad_ch].pin,io_to_ad[ad_ch].mode);
//ADC控制寄存器设置,时钟9M
LPC_ADC->ADCR = AD_CH_SEL(0) | AD_CLK_DIV(2) | AD_WORK_SOFT | AD_PDN_DISABLE | AD_EDGE_UP | AD_START(0);
}
//初始化adc
adc_init(AD_CH(0));//正压
adc_init(AD_CH(1));//负压
adc_init(AD_CH(2));//鞘流压
FPGA
和FPGA交互,从FPGA读取数据,或者向FPGA写入数据;
使用场景包括:
1、通过FPGA读取温度值;
2、通过FPGA读写阀状态;
3、通过FPGA读写泵状态;
4、通过FPGA读取试剂检测占空比;
5、通过FPGA查询外部开关状态()
6、通过FPGA读取电机光耦状态,剩余运动步数;
uint8 get_checksum_from_fpga(uint16 fpga_addr)
{
uint8 check_sum = 0;
//延时
delay_clocks();
delay_clocks();
//写地址
set_fpga_addr_bus(fpga_addr);
//延时
delay_clocks();
delay_clocks();
//读信号有效
FPGA_RD_L();
//延时
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
//读取
check_sum = get_fpga_data_bus();
//读结束
FPGA_RD_H();
//延时
delay_clocks();
return check_sum;
}
uint8 set_checksum_to_fpga(uint16 fpga_addr, uint8 check_sum)
{
uint8 check_state = 0;
//延时
delay_clocks();
delay_clocks();
//向数据线写校验
set_fpga_data_bus(check_sum);
//向地址线写地址
set_fpga_addr_bus(fpga_addr);
//延时
delay_clocks();
delay_clocks();
//写信号有效
FPGA_WR_L();
//延时
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
//写结束
FPGA_WR_H();
//获取校验状态
check_state = FPGA_WR_STATE();
check_state = FPGA_WR_STATE();
//延时
delay_clocks();
return check_state;
}
int32 fpga_read(fpga_data *pfpga_data, uint8 data_len)
{
int32 lret = EXIT_FAILURE_LOCOAL;
uint16 check_sum_cal = 0;
uint8 check_sum_get = 0;
uint8 check_sum_temp = 0;
uint8 i = 0;
uint8 read_times = 0;
do
{
if(INVALID_POINTER(pfpga_data) || (1 > data_len))
{
// debug_msg("E:input param error!",__FILE__,__LINE__);
break;
}
//置数据线为输入
FPGA_WR_H();
FPGA_RD_H();
set_fpga_data_bus_dir(GPIO_INPUT);
while(1)
{
//片选有效
FPGA_CS_L();
check_sum_cal = 0;
//延时
delay_clocks();
for(i = 0;i < data_len;i++)
{
//写地址
set_fpga_addr_bus(pfpga_data[i].addr);
//计算校验和,包括地址和数据
check_sum_cal += pfpga_data[i].addr;
//延时
delay_clocks();
//单次读有效
FPGA_RD_L();
//延时
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
//读取数据
pfpga_data[i].data = get_fpga_data_bus();
//计算校验和
check_sum_cal += pfpga_data[i].data;
//单次读结束
FPGA_RD_H();
//延时
delay_clocks();
}
//延时
delay_clocks();
delay_clocks();
//片选无效
FPGA_CS_H();
//读校验
check_sum_get = get_checksum_from_fpga(REG_ARM_READ_CHECKSUM);
//校验比较
check_sum_temp = (uint8)(check_sum_cal & 0x00ff);
check_sum_temp += (uint8)(check_sum_cal >> 8);
check_sum_temp = ~check_sum_temp;
if(check_sum_get != check_sum_temp)
{
//读失败重复读,次数限制3次
if(read_times < 3)
{
read_times++;
}
else
{
break;
}
}
else //校验正确
{
lret = EXIT_SUCCESS_LOCOAL;
break;
}
}
}while(0);
return lret;
}
int32 fpga_write(fpga_data *pfpga_data, uint8 data_len)
{
int32 lret = EXIT_FAILURE_LOCOAL;
uint16 check_sum_cal = 0;
uint8 check_sum_temp = 0;
uint8 i = 0;
uint8 write_times = 0;
do
{
if(INVALID_POINTER(pfpga_data) || (1 > data_len))
{
// debug_msg("E:input param error!",__FILE__,__LINE__);
break;
}
//置数据线为输出
FPGA_RD_H();
FPGA_WR_H();
set_fpga_data_bus_dir(GPIO_OUTPUT);
while(1)
{
//片选有效
FPGA_CS_L();
check_sum_cal = 0;
for(i = 0;i < data_len;i++)
{
//延时
delay_clocks();
//向数据总线上写数据
set_fpga_data_bus(pfpga_data[i].data);
check_sum_cal += pfpga_data[i].data;
//向地址线写地址
set_fpga_addr_bus(pfpga_data[i].addr);
check_sum_cal += pfpga_data[i].addr;
//延时
delay_clocks();
//单次写信号有效
FPGA_WR_L();
//延时
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
delay_clocks();
//单次写结束
FPGA_WR_H();
//延时
delay_clocks();
}
//延时
delay_clocks();
//片选失效
FPGA_CS_H();
//写校验
check_sum_temp = (uint8)(check_sum_cal & 0x00ff);
check_sum_temp += (uint8)(check_sum_cal >> 8);
check_sum_temp = ~check_sum_temp;
if(WR_FPGA_CKECKSUM_ERR == set_checksum_to_fpga(REG_ARM_WRITE_CHECKSUM, check_sum_temp))
{
// debug_msg("E:fpga ReWR!",__FILE__,__LINE__);
if(write_times < 3)
{
write_times++;
}
else
{
// debug_msg("E:fpga write error!",__FILE__,__LINE__);
// lret = -ERR_DB_WRITE_FPGA;
break;
}
}
else
{
lret = EXIT_SUCCESS_LOCOAL;
break;
}
}
//数据总线置为输入
set_fpga_data_bus_dir(GPIO_INPUT);
}while(0);
return lret;
}