mirror of
https://github.com/eddyem/IR-controller.git
synced 2026-03-21 17:20:59 +03:00
Add something to stepper_motors.c + make little modifications
This commit is contained in:
@@ -105,7 +105,7 @@ uint32_t read_ADC_data(){
|
||||
*/
|
||||
uint8_t check_data_ready(){
|
||||
uint8_t ret = 0;
|
||||
//DBG("check_data_ready\r\n");
|
||||
//DBG("check_data_ready\n");
|
||||
uint8_t x = sendByte(STAT_REGISTER | READ_FROM_REG, 0);
|
||||
if(data_error){
|
||||
DBG("some data error\n");
|
||||
@@ -231,7 +231,7 @@ uint32_t read_AD7794(uint8_t channel){
|
||||
if(!dr) return AD7794_NOTRDY;
|
||||
break;
|
||||
default: // last step -> return readed data
|
||||
//P("\r\n", uart1_send);
|
||||
//P("\n", uart1_send);
|
||||
N = 0;
|
||||
return read_ADC_data();
|
||||
}
|
||||
|
||||
@@ -198,15 +198,17 @@ static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *
|
||||
|
||||
switch (req->bRequest) {
|
||||
case SET_CONTROL_LINE_STATE:{
|
||||
P("SET_CONTROL_LINE_STATE\r\n", uart1_send);
|
||||
print_int(req->wValue, uart1_send);
|
||||
newline(uart1_send);
|
||||
#ifdef EBUG
|
||||
P("SET_CONTROL_LINE_STATE\n", uart1_send);
|
||||
print_int(req->wValue, uart1_send);
|
||||
newline(uart1_send);
|
||||
#endif
|
||||
if(req->wValue){ // terminal is opened
|
||||
USB_connected = 1;
|
||||
//P("\r\n\tUSB connected!\r\n", uart1_send);
|
||||
//P("\n\tUSB connected!\n", uart1_send);
|
||||
}else{ // terminal is closed
|
||||
USB_connected = 0;
|
||||
//P("\r\n\tUSB disconnected!\r\n", uart1_send);
|
||||
//P("\n\tUSB disconnected!\n", uart1_send);
|
||||
}
|
||||
/*
|
||||
* This Linux cdc_acm driver requires this to be implemented
|
||||
@@ -225,11 +227,15 @@ newline(uart1_send);
|
||||
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
||||
}break;
|
||||
case SET_LINE_CODING:
|
||||
P("SET_LINE_CODING, len=", uart1_send);
|
||||
#ifdef EBUG
|
||||
P("SET_LINE_CODING, len=", uart1_send);
|
||||
#endif
|
||||
if (!len || (*len != sizeof(struct usb_cdc_line_coding)))
|
||||
return 0;
|
||||
print_int(*len, uart1_send);
|
||||
newline(uart1_send);
|
||||
#ifdef EBUG
|
||||
print_int(*len, uart1_send);
|
||||
newline(uart1_send);
|
||||
#endif
|
||||
memcpy((void *)&lc, (void *)*buf, *len);
|
||||
// Mark & Space parity don't support by hardware, check it
|
||||
if(lc.bParityType == USB_CDC_MARK_PARITY || lc.bParityType == USB_CDC_SPACE_PARITY){
|
||||
@@ -243,10 +249,14 @@ newline(uart1_send);
|
||||
if(len && *len == sizeof(struct usb_cdc_line_coding))
|
||||
memcpy((void *)*buf, (void *)&linecoding, sizeof(struct usb_cdc_line_coding));
|
||||
//usbd_ep_write_packet(usbd_dev, 0x83, (char*)&linecoding, sizeof(linecoding));
|
||||
P("GET_LINE_CODING\r\n", uart1_send);
|
||||
#ifdef EBUG
|
||||
P("GET_LINE_CODING\n", uart1_send);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
P("UNKNOWN\r\n", uart1_send);
|
||||
#ifdef EBUG
|
||||
P("UNKNOWN\n", uart1_send);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -300,11 +310,10 @@ mutex_t send_block_mutex = MUTEX_UNLOCKED;
|
||||
void usb_send(uint8_t byte){
|
||||
mutex_lock(&send_block_mutex);
|
||||
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
|
||||
mutex_unlock(&send_block_mutex);
|
||||
if(USB_Tx_ptr == USB_TX_DATA_SIZE){ // buffer can be overflowed - send it!
|
||||
mutex_unlock(&send_block_mutex);
|
||||
usb_send_buffer();
|
||||
}else
|
||||
mutex_unlock(&send_block_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -149,22 +149,30 @@ uint8_t adc_channel_array[16] = {9,8,15,14,7,6,5,4};
|
||||
*/
|
||||
void adc_dma_on(){
|
||||
// first configure DMA1 Channel1 (ADC1)
|
||||
rcc_periph_clock_enable(RCC_DMA1); // RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL1); //DMA_DeInit(DMA1_Channel1);
|
||||
dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(ADC_DR(ADC1))); // DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
|
||||
dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) ADC_value); // DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_value;
|
||||
dma_set_number_of_data(DMA1, DMA_CHANNEL1, ADC_CHANNELS_NUMBER); // DMA_InitStructure.DMA_BufferSize = 1;
|
||||
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT); // DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
|
||||
dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT); // DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
|
||||
dma_enable_circular_mode(DMA1, DMA_CHANNEL1); // DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR_PL_HIGH); // DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
nvic_disable_irq(NVIC_DMA1_CHANNEL1_IRQ);
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL1);
|
||||
DMA1_CPAR1 = (uint32_t) &(ADC_DR(ADC1));
|
||||
DMA1_CMAR1 = (uint32_t) ADC_value;
|
||||
DMA1_CNDTR1 = ADC_CHANNELS_NUMBER;
|
||||
DMA1_CCR1 = DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
|
||||
| DMA_CCR_CIRC | DMA_CCR_PL_HIGH | DMA_CCR_EN;
|
||||
adc_enable_dma(ADC1);
|
||||
adc_power_on(ADC1);
|
||||
/*
|
||||
dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(ADC_DR(ADC1)));
|
||||
dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) ADC_value);
|
||||
dma_set_number_of_data(DMA1, DMA_CHANNEL1, ADC_CHANNELS_NUMBER);
|
||||
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1);
|
||||
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
|
||||
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL1);
|
||||
dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT);
|
||||
dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT);
|
||||
dma_enable_circular_mode(DMA1, DMA_CHANNEL1);
|
||||
dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR_PL_HIGH);
|
||||
dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL1);
|
||||
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1);
|
||||
dma_enable_channel(DMA1, DMA_CHANNEL1); // DMA_Cmd(DMA1_Channel1, ENABLE);
|
||||
dma_enable_channel(DMA1, DMA_CHANNEL1);
|
||||
*/
|
||||
}
|
||||
|
||||
void ADC_init(){
|
||||
@@ -181,8 +189,7 @@ void ADC_init(){
|
||||
|
||||
// Make sure the ADC doesn't run during config
|
||||
adc_off(ADC1);
|
||||
|
||||
adc_dma_on();
|
||||
rcc_periph_clock_enable(RCC_DMA1);
|
||||
|
||||
// Configure ADC as continuous scan mode with DMA
|
||||
adc_set_dual_mode(ADC_CR1_DUALMOD_IND); // ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
|
||||
@@ -192,8 +199,8 @@ void ADC_init(){
|
||||
adc_set_right_aligned(ADC1); // ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5CYC); // ADC_SampleTime_239Cycles5
|
||||
//adc_set_sample_time(ADC1, ADC_CHANNEL8, ADC_SMPR_SMP_239DOT5CYC); // ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);
|
||||
adc_enable_dma(ADC1); // ADC_DMACmd(ADC1, ENABLE);
|
||||
adc_power_on(ADC1); // ADC_Cmd(ADC1, ENABLE);
|
||||
|
||||
adc_dma_on();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,16 +215,22 @@ void ADC_calibrate_and_start(){
|
||||
adc_start_conversion_direct(ADC1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t tim2_buff[TIM2_DMABUFF_SIZE];
|
||||
uint16_t tim2_inbuff[TIM2_DMABUFF_SIZE];
|
||||
int tum2buff_ctr = 0;
|
||||
uint8_t ow_done = 1;
|
||||
/**
|
||||
* this function sends bits of ow_byte (LSB first) to 1-wire line
|
||||
* @param ow_byte - byte to convert
|
||||
* @param Nbits - number of bits to send
|
||||
* @param ini - 1 to zero counter
|
||||
*/
|
||||
uint8_t OW_add_byte(uint8_t ow_byte, uint8_t Nbits, uint8_t ini){
|
||||
uint8_t OW_add_byte(_U_ uint8_t ow_byte, _U_ uint8_t Nbits, _U_ uint8_t ini){
|
||||
uint8_t i, byte;
|
||||
if(ini) tum2buff_ctr = 0;
|
||||
if(Nbits == 0) return 0;
|
||||
@@ -232,6 +245,26 @@ uint8_t OW_add_byte(uint8_t ow_byte, uint8_t Nbits, uint8_t ini){
|
||||
if(tum2buff_ctr == TIM2_DMABUFF_SIZE) return 0; // avoid buffer overflow
|
||||
ow_byte = ow_byte >> 1;
|
||||
}
|
||||
// print_int(tum2buff_ctr, lastsendfun);
|
||||
// MSG(" bytes in send buffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Nbytes bytes 0xff for reading sequence
|
||||
*/
|
||||
uint8_t OW_add_read_seq(uint8_t Nbytes){
|
||||
uint8_t i;
|
||||
if(Nbytes == 0) return 0;
|
||||
Nbytes *= 8; // 8 bits for each byte
|
||||
for(i = 0; i < Nbytes; i++){
|
||||
tim2_buff[tum2buff_ctr++] = 1;
|
||||
if(tum2buff_ctr == TIM2_DMABUFF_SIZE) return 0;
|
||||
}
|
||||
#ifdef EBUG
|
||||
print_int(tum2buff_ctr, lastsendfun);
|
||||
MSG(" bytes in send buffer\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -241,47 +274,79 @@ uint8_t OW_add_byte(uint8_t ow_byte, uint8_t Nbits, uint8_t ini){
|
||||
* @param N - data length (in **bytes**)
|
||||
* @outbuf - where to place data
|
||||
*/
|
||||
void read_from_OWbuf(uint8_t start_idx, uint8_t N, uint8_t *outbuf){
|
||||
void read_from_OWbuf(_U_ uint8_t start_idx, _U_ uint8_t N, _U_ uint8_t *outbuf){
|
||||
uint8_t i, j, last = start_idx + N * 8, byte;
|
||||
if(last >= TIM2_DMABUFF_SIZE) last = TIM2_DMABUFF_SIZE;
|
||||
for(i = start_idx; i < last;){
|
||||
byte = 0;
|
||||
for(j = 0; j < 8; j++, byte <<= 1){
|
||||
if(tim2_inbuff[i++] > OW_READ1) byte |= 1;
|
||||
for(j = 0; j < 8; j++){
|
||||
byte >>= 1;
|
||||
#ifdef EBUG
|
||||
print_int(tim2_inbuff[i], lastsendfun);
|
||||
MSG(" ");
|
||||
#endif
|
||||
if(tim2_inbuff[i++] < OW_READ1)
|
||||
byte |= 0x80;
|
||||
}
|
||||
*outbuf++ = byte;
|
||||
#ifdef EBUG
|
||||
MSG("readed \n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// there's a mistake in opencm3, so redefine this if needed (TIM_CCMR2_CC3S_IN_TI1 -> TIM_CCMR2_CC3S_IN_TI4)
|
||||
#ifndef TIM_CCMR2_CC3S_IN_TI4
|
||||
#define TIM_CCMR2_CC3S_IN_TI4 (2)
|
||||
#endif
|
||||
void init_ow_dmatimer(){ // tim2_ch4 - PA3, no remap
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO3);
|
||||
rcc_periph_clock_enable(RCC_TIM2);
|
||||
rcc_periph_clock_enable(RCC_DMA1);
|
||||
timer_reset(TIM2);
|
||||
// timers have frequency of 1MHz -- 1us for one step
|
||||
// 36MHz of APB1
|
||||
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
||||
// 72MHz div 72 = 1MHz
|
||||
timer_set_prescaler(TIM2, 71); // prescaler is (div - 1)
|
||||
timer_continuous_mode(TIM2); // automatically reload
|
||||
timer_disable_preload(TIM2); // force changing period
|
||||
timer_set_period(TIM2, OW_BIT); // bit length
|
||||
timer_enable_update_event(TIM2);
|
||||
timer_set_oc_polarity_high(TIM2, TIM_OC4);
|
||||
timer_set_oc_mode(TIM2, TIM_OC4, TIM_OCM_PWM1); // edge-aligned mode
|
||||
timer_disable_oc_preload(TIM2, TIM_OC4);
|
||||
timer_set_oc_value(TIM2, TIM_OC4, OW_RESET);
|
||||
timer_enable_oc_output(TIM2, TIM_OC4);
|
||||
|
||||
timer_disable_counter(TIM2);
|
||||
timer_disable_irq(TIM2, TIM_DIER_UIE);
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
gpio_set(GPIOA, GPIO3);
|
||||
TIM2_PSC = 71; // prescaler is (div - 1)
|
||||
TIM2_CR1 &= ~(TIM_CR1_OPM | TIM_CR1_UDIS); // continuous mode & enable update events
|
||||
TIM2_CR1 |= TIM_CR1_ARPE; // changing period immediately
|
||||
TIM2_ARR = OW_BIT; // default period of timer
|
||||
// PWM_OUT: TIM2_CH4; capture: TIM2_CH3
|
||||
// PWM edge-aligned mode & enable preload for CCR4, CC3 takes input from TI4
|
||||
TIM2_CCMR2 = TIM_CCMR2_OC4M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_CC3S_IN_TI4;
|
||||
TIM2_CCR4 = 0; // set output value to 1 by clearing CCR4
|
||||
TIM2_EGR = TIM_EGR_UG; // update values of ARR & CCR4
|
||||
// set low polarity for CC4, high for CC4 & enable CC4 out and CC3 in
|
||||
TIM2_CCER = TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
|
||||
|
||||
// TIM2_CH4 - DMA1, channel 7
|
||||
rcc_periph_clock_enable(RCC_DMA1);
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL7);
|
||||
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t) &(TIM_CCR4(TIM2)));
|
||||
DMA1_CCR7 = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
|
||||
| DMA_CCR_TEIE | DMA_CCR_TCIE | DMA_CCR_PL_HIGH;
|
||||
/*
|
||||
DMA1_CCR7 |= DMA_CCR_DIR; // dma_set_read_from_memory(DMA1, DMA_CHANNEL7);
|
||||
DMA1_CCR7 |= DMA_CCR_MINC; // dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
|
||||
//dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
|
||||
DMA1_CCR7 |= DMA_CCR_PSIZE_16BIT; // dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_16BIT);
|
||||
DMA1_CCR7 |= DMA_CCR_MSIZE_16BIT; // dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_16BIT);
|
||||
DMA1_CCR7 |= DMA_CCR_TEIE; // dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL7);
|
||||
DMA1_CCR7 |= DMA_CCR_TCIE; // dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
|
||||
*/
|
||||
nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ); // enable dma1_channel7_isr
|
||||
}
|
||||
|
||||
void run_dmatimer(){
|
||||
ow_done = 0;
|
||||
adc_disable_dma(ADC1); // turn off DMA & ADC
|
||||
adc_off(ADC1);
|
||||
DMA1_IFCR = DMA_ISR_TEIF7|DMA_ISR_HTIF7|DMA_ISR_TCIF7|DMA_ISR_GIF7 |
|
||||
DMA_ISR_TEIF1|DMA_ISR_HTIF1|DMA_ISR_TCIF1|DMA_ISR_GIF1; // clear flags
|
||||
|
||||
//init_ow_dmatimer();
|
||||
/*
|
||||
// TIM2_CH4 - DMA1, channel 7
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL7);
|
||||
dma_set_read_from_memory(DMA1, DMA_CHANNEL7);
|
||||
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
|
||||
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
|
||||
@@ -289,146 +354,116 @@ void init_ow_dmatimer(){ // tim2_ch4 - PA3, no remap
|
||||
dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_16BIT);
|
||||
dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL7);
|
||||
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
|
||||
dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t)tim2_buff);
|
||||
|
||||
nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ); // enable dma1_channel7_isr
|
||||
|
||||
// capture: TIM2_CH3
|
||||
timer_ic_set_input(TIM2, TIM_IC3, TIM_IC_IN_TI4);
|
||||
timer_set_oc_polarity_high(TIM2, TIM_OC3);
|
||||
timer_ic_enable(TIM2, TIM_IC3);
|
||||
//timer_enable_oc_output(TIM2, TIM_OC3);
|
||||
//gpio_set(GPIOA, GPIO3);
|
||||
ow_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* reconfigure DMA1_1 for 1-wire
|
||||
*/
|
||||
void ow_dma_on(){
|
||||
*/
|
||||
DMA1_CCR7 &= ~DMA_CCR_EN; // disable (what if it's enabled?) to set address
|
||||
DMA1_CPAR7 = (uint32_t) &(TIM_CCR4(TIM2)); // dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t) &(TIM_CCR4(TIM2)));
|
||||
DMA1_CMAR7 = (uint32_t) tim2_buff; // dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t)tim2_buff);
|
||||
DMA1_CNDTR7 = tum2buff_ctr;//dma_set_number_of_data(DMA1, DMA_CHANNEL7, tum2buff_ctr);
|
||||
// TIM2_CH4 - DMA1, channel 7
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL1);
|
||||
dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(TIM_CCR3(TIM2)));
|
||||
dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) tim2_inbuff);
|
||||
DMA1_CCR1 = DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
|
||||
| DMA_CCR_TEIE | DMA_CCR_TCIE | DMA_CCR_PL_HIGH;
|
||||
/*
|
||||
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1);
|
||||
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
|
||||
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL1);
|
||||
dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_16BIT);
|
||||
dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT);
|
||||
nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
|
||||
dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL1);
|
||||
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1);
|
||||
}
|
||||
*/
|
||||
DMA1_CPAR1 = (uint32_t) &(TIM_CCR3(TIM2)); //dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(TIM_CCR3(TIM2)));
|
||||
DMA1_CMAR1 = (uint32_t) tim2_inbuff; //dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) tim2_inbuff);
|
||||
DMA1_CNDTR1 = tum2buff_ctr; //dma_set_number_of_data(DMA1, DMA_CHANNEL1, tum2buff_ctr);
|
||||
nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
|
||||
|
||||
void run_dmatimer(){
|
||||
//int i;
|
||||
ow_done = 0;
|
||||
ow_dma_on();
|
||||
DMA1_IFCR = DMA_ISR_TEIF7|DMA_ISR_HTIF7|DMA_ISR_TCIF7|DMA_ISR_GIF7 |
|
||||
DMA_ISR_TEIF1|DMA_ISR_HTIF1|DMA_ISR_TCIF1|DMA_ISR_GIF1; // clear flags
|
||||
TIM_SR(TIM2) = 0;
|
||||
timer_set_period(TIM2, OW_BIT); // bit length
|
||||
dma_set_number_of_data(DMA1, DMA_CHANNEL7, tum2buff_ctr);
|
||||
//timer_set_dma_on_compare_event(TIM2);
|
||||
timer_set_dma_on_update_event(TIM2);
|
||||
timer_ic_enable(TIM2, TIM_IC3);
|
||||
dma_enable_channel(DMA1, DMA_CHANNEL7);
|
||||
DMA1_CCR7 |= DMA_CCR_EN; //dma_enable_channel(DMA1, DMA_CHANNEL7);
|
||||
DMA1_CCR1 |= DMA_CCR_EN; //dma_enable_channel(DMA1, DMA_CHANNEL1);
|
||||
|
||||
//for(i = 0; i < TIM2_DMABUFF_SIZE; i++) tim2_inbuff[i] = 0;
|
||||
dma_set_number_of_data(DMA1, DMA_CHANNEL1, tum2buff_ctr);
|
||||
dma_enable_channel(DMA1, DMA_CHANNEL1);
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_CR1 &= ~TIM_CR1_OPM; // continuous mode
|
||||
TIM2_ARR = OW_BIT; // bit length
|
||||
TIM2_EGR = TIM_EGR_UG; // update value of ARR
|
||||
|
||||
timer_enable_irq(TIM2, TIM_DIER_UDE | TIM_DIER_CC4DE | TIM_DIER_CC3DE);
|
||||
TIM2_CCER |= TIM_CCER_CC4P | TIM_CCER_CC4E;
|
||||
TIM2_CR1 |= TIM_CR1_CEN; // timer_enable_counter(TIM2);
|
||||
}
|
||||
TIM2_CR2 &= ~TIM_CR2_CCDS; // timer_set_dma_on_compare_event(TIM2);
|
||||
TIM2_CCER |= TIM_CCER_CC3E; // enable input capture
|
||||
TIM2_DIER = TIM_DIER_CC4DE | TIM_DIER_CC3DE; // enable DMA events
|
||||
// set low polarity, enable cc out & enable input capture
|
||||
TIM2_CCER |= TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
|
||||
TIM2_CR1 |= TIM_CR1_CEN; // run timer
|
||||
|
||||
void ow_reset(){
|
||||
ow_done = 0;
|
||||
timer_disable_counter(TIM2);
|
||||
DMA1_IFCR = DMA_ISR_TEIF7|DMA_ISR_HTIF7|DMA_ISR_TCIF7|DMA_ISR_GIF7 |
|
||||
DMA_ISR_TEIF1|DMA_ISR_HTIF1|DMA_ISR_TCIF1|DMA_ISR_GIF1; // clear flags
|
||||
TIM_SR(TIM2) = 0;
|
||||
timer_set_period(TIM2, OW_RESET*2); // reset length
|
||||
timer_set_oc_value(TIM2, TIM_OC4, OW_RESET);
|
||||
|
||||
timer_ic_set_input(TIM2, TIM_IC3, TIM_IC_IN_TI4);
|
||||
timer_set_oc_polarity_high(TIM2, TIM_OC3);
|
||||
timer_ic_enable(TIM2, TIM_IC3);
|
||||
|
||||
// timer_enable_irq(TIM2, TIM_DIER_CC3DE);
|
||||
timer_set_dma_on_update_event(TIM2); // wait until end of signal!
|
||||
timer_enable_irq(TIM2, TIM_DIER_UIE | TIM_DIER_CC3IE);
|
||||
nvic_enable_irq(NVIC_TIM2_IRQ);
|
||||
|
||||
//timer_generate_event(TIM2, TIM_SR_UIF);
|
||||
/*
|
||||
tim2_inbuff[0] = 0;
|
||||
dma_set_number_of_data(DMA1, DMA_CHANNEL1, 6);
|
||||
dma_enable_channel(DMA1, DMA_CHANNEL1); // enable only reading - for interrupt
|
||||
*/
|
||||
// NOT USE THIS: wery long
|
||||
//timer_set_oc_polarity_low(TIM2, TIM_OC4);
|
||||
//timer_enable_oc_output(TIM2, TIM_OC4);
|
||||
TIM2_CCER |= TIM_CCER_CC4P | TIM_CCER_CC4E;
|
||||
TIM2_CR1 |= TIM_CR1_CEN; // timer_enable_counter(TIM2);
|
||||
}
|
||||
|
||||
uint16_t rstat = 0, lastcc3;
|
||||
void ow_reset(){
|
||||
ow_done = 0;
|
||||
rstat = 0;
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_DIER = 0; // disable timer interrupts
|
||||
TIM2_ARR = OW_RESET_TIME; // set period to 1ms
|
||||
TIM2_CCR4 = OW_RESET; // zero pulse length
|
||||
TIM2_EGR = TIM_EGR_UG; // update values of ARR & CCR4
|
||||
TIM2_CR1 |= TIM_CR1_OPM | TIM_CR1_CEN; // we need only single pulse & run timer
|
||||
TIM2_SR = 0; // clear update flag generated after timer's running
|
||||
TIM2_DIER = TIM_DIER_UIE | TIM_DIER_CC3IE; // generate interrupts on update event & cc
|
||||
nvic_enable_irq(NVIC_TIM2_IRQ);
|
||||
}
|
||||
|
||||
void tim2_isr(){
|
||||
if(timer_get_flag(TIM2, TIM_SR_UIF)){
|
||||
timer_clear_flag(TIM2, TIM_SR_UIF);
|
||||
TIM2_CCER &= ~TIM_CCER_CC4P; //timer_set_oc_polarity_high(TIM2, TIM_OC4);
|
||||
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
|
||||
TIM2_SR &= ~TIM_SR_UIF; // clear flag
|
||||
TIM2_DIER = 0; // disable all timer interrupts
|
||||
TIM2_CCR4 = 0; // set output value to 1
|
||||
TIM2_EGR |= TIM_EGR_UG; // generate update event to change value in CCR4
|
||||
TIM2_CR1 &= ~TIM_CR1_CEN; // timer_disable_counter(TIM2);
|
||||
gpio_set(GPIOA, GPIO3);
|
||||
timer_disable_irq(TIM2, TIM_DIER_UIE | TIM_DIER_CC3IE);
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
ow_done = 1;
|
||||
rstat = lastcc3;
|
||||
print_int(rstat, lastsendfun);
|
||||
MSG("\n");
|
||||
/* print_int(rstat, lastsendfun);
|
||||
MSG("\n");*/
|
||||
}
|
||||
if(timer_get_flag(TIM2, TIM_SR_CC3IF)){
|
||||
timer_clear_flag(TIM2, TIM_SR_CC3IF);
|
||||
lastcc3 = TIM_CCR3(TIM2);
|
||||
if(TIM2_SR & TIM_SR_CC3IF){ // we need this interrupt to store CCR3 value
|
||||
TIM2_SR = 0; // clear flag (we've manage TIM_SR_UIF before, so can simply do =0)
|
||||
lastcc3 = TIM2_CCR3;
|
||||
//TIM2_DIER &= ~TIM_DIER_CC3IE; // disable CCR3 interrupts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dma1_channel7_isr(){
|
||||
if(DMA1_ISR & DMA_ISR_TCIF7) {
|
||||
DMA1_IFCR = DMA_IFCR_CTCIF7;
|
||||
dma_disable_channel(DMA1, DMA_CHANNEL7);
|
||||
timer_disable_irq(TIM2, TIM_DIER_CC4DE);
|
||||
if(DMA1_ISR & DMA_ISR_TCIF7){
|
||||
DMA1_IFCR = DMA_IFCR_CTCIF7; // clear flag
|
||||
DMA1_CCR7 &= ~DMA_CCR_EN; // disable DMA1 channel 7
|
||||
//TIM2_DIER &= ~TIM_DIER_CC4DE;
|
||||
}else if(DMA1_ISR & DMA_ISR_TEIF7){
|
||||
DMA1_IFCR = DMA_IFCR_CTEIF7;
|
||||
MSG("out transfer error\n");
|
||||
MSG("DMA out transfer error\n");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ow_done = 1;
|
||||
void dma1_channel1_isr(){
|
||||
int i;
|
||||
//int i;
|
||||
if(DMA1_ISR & DMA_ISR_TCIF1) {
|
||||
DMA1_IFCR = DMA_IFCR_CTCIF1;
|
||||
TIM2_CCER &= ~TIM_CCER_CC4P; //timer_set_oc_polarity_high(TIM2, TIM_OC4);
|
||||
TIM2_CR1 &= ~TIM_CR1_CEN; // timer_disable_counter(TIM2);
|
||||
timer_disable_irq(TIM2, TIM_DIER_CC3DE);
|
||||
gpio_set(GPIOA, GPIO3);
|
||||
dma_disable_channel(DMA1, DMA_CHANNEL1);
|
||||
//TIM2_DIER &= ~TIM_DIER_CC3DE;
|
||||
DMA1_CCR1 &= ~DMA_CCR_EN; // disable DMA1 channel 1
|
||||
nvic_disable_irq(NVIC_DMA1_CHANNEL1_IRQ);
|
||||
ow_done = 1;
|
||||
for(i = 0; i < tum2buff_ctr; i++){
|
||||
/* for(i = 0; i < tum2buff_ctr; i++){
|
||||
print_int(tim2_inbuff[i], lastsendfun);
|
||||
MSG(" ");
|
||||
}
|
||||
MSG("\n");
|
||||
MSG("\n");*/
|
||||
}else if(DMA1_ISR & DMA_ISR_TEIF1){
|
||||
DMA1_IFCR = DMA_IFCR_CTEIF1;
|
||||
MSG("in transfer error\n");
|
||||
MSG("DMA in transfer error\n");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t OW_get_reset_status(){
|
||||
/* print_int(rstat, lastsendfun);
|
||||
MSG("\n");*/
|
||||
if(rstat < OW_PRESENT) return 0; // no devices
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
|
||||
#define TIM2_DMABUFF_SIZE 128
|
||||
// 1-wire zero-state lengths (in us minus 1)
|
||||
#define OW_1 (9)
|
||||
#define OW_0 (69)
|
||||
#define OW_READ1 (14)
|
||||
#define OW_BIT (79)
|
||||
#define OW_RESET (499)
|
||||
#define OW_PRESENT (599)
|
||||
#define OW_1 (9)
|
||||
#define OW_0 (69)
|
||||
#define OW_READ1 (14)
|
||||
#define OW_BIT (79)
|
||||
#define OW_RESET (499)
|
||||
#define OW_RESET_TIME (999)
|
||||
#define OW_PRESENT (549)
|
||||
|
||||
extern volatile uint16_t ADC_value[]; // ADC DMA value
|
||||
|
||||
@@ -60,10 +61,10 @@ void ADC_calibrate_and_start();
|
||||
// change signal level on USB diconnect pin
|
||||
#define usb_disc_high() gpio_set(USB_DISC_PORT, USB_DISC_PIN)
|
||||
#define usb_disc_low() gpio_clear(USB_DISC_PORT, USB_DISC_PIN)
|
||||
// in case of pnp bipolar transistor on 1.5k pull-up disconnect means low level
|
||||
// in case of p-channel FET on 1.5k pull-up change on/off disconnect means high level
|
||||
#define usb_disconnect() usb_disc_low()
|
||||
#define usb_connect() usb_disc_high()
|
||||
// in case of n-channel FET on 1.5k pull-up change on/off disconnect means low level
|
||||
// in case of pnp bipolar transistor or p-channel FET on 1.5k pull-up disconnect means high level
|
||||
#define usb_disconnect() usb_disc_high()
|
||||
#define usb_connect() usb_disc_low()
|
||||
|
||||
/*
|
||||
* Stepper motors
|
||||
@@ -71,15 +72,15 @@ void ADC_calibrate_and_start();
|
||||
* moved to stepper_motors.c
|
||||
*/
|
||||
// PE7..11 - EN
|
||||
#define MOROT_EN_MASK (0x1f << 7)
|
||||
#define MOTOR_EN_MASK (0x1f << 7)
|
||||
#define MOTOR_EN_PORT (GPIOE)
|
||||
// N == 1..5
|
||||
#define MOTOR_EN_PIN(N) (GPIO6 << (N))
|
||||
// N == 0..4
|
||||
#define MOTOR_EN_PIN(N) (GPIO7 << (N))
|
||||
// PE0..PE5 - DIR
|
||||
#define MOROT_DIR_MASK (0x1f)
|
||||
#define MOTOR_DIR_MASK (0x1f)
|
||||
#define MOTOR_DIR_PORT (GPIOE)
|
||||
// N == 1..5
|
||||
#define MOTOR_DIR_PIN(N) (GPIO0 << (N - 1))
|
||||
// N == 0..4
|
||||
#define MOTOR_DIR_PIN(N) (GPIO0 << (N))
|
||||
// timers: TIM1 - PC6, TIM2 - PD15
|
||||
#define MOTOR_TIM1_PORT (GPIOC)
|
||||
#define MOTOR_TIM1_PIN (GPIO6)
|
||||
@@ -102,6 +103,7 @@ extern uint8_t ow_done;
|
||||
void ow_dma_on();
|
||||
void adc_dma_on();
|
||||
uint8_t OW_add_byte(uint8_t ow_byte, uint8_t Nbits, uint8_t ini);
|
||||
uint8_t OW_add_read_seq(uint8_t Nbytes);
|
||||
void read_from_OWbuf(uint8_t start_idx, uint8_t N, uint8_t *outbuf);
|
||||
void ow_reset();
|
||||
uint8_t OW_get_reset_status();
|
||||
|
||||
Binary file not shown.
@@ -115,7 +115,7 @@ void AD7794_init(){
|
||||
if(i != ADC_NO_ERROR){
|
||||
if(i == ADC_ERR_NO_DEVICE){
|
||||
// print_int(curSPI, lastsendfun);
|
||||
MSG(": ADC signal is absent! Check connection.\r\n");
|
||||
MSG("ADC signal is absent! Check connection.\n");
|
||||
/* if(curSPI == 1){
|
||||
curSPI = 2;
|
||||
switch_SPI(SPI2);
|
||||
@@ -127,10 +127,10 @@ void AD7794_init(){
|
||||
}else{
|
||||
if(!setup_AD7794(INTREFIN | REF_DETECTION | UNIPOLAR_CODING, IEXC_DIRECT | IEXC_1MA)
|
||||
|| !AD7794_calibration(0)){
|
||||
MSG("Error: can't initialize AD7794!\r\n");
|
||||
MSG("Error: can't initialize AD7794!\n");
|
||||
}else{
|
||||
ad7794_on = 1;
|
||||
DBG("ADC ready\r\n");
|
||||
DBG("ADC ready\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,29 +140,24 @@ int main(){
|
||||
uint32_t Old_timer = 0, lastTRDread = 0, lastTmon = 0;
|
||||
//SPI_read_status SPI_stat;
|
||||
|
||||
//rcc_clock_setup_in_hsi_out_48mhz();
|
||||
// RCC clocking: 8MHz oscillator -> 72MHz system
|
||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||
usb_disconnect(); // turn off USB while initializing all
|
||||
|
||||
// GPIO
|
||||
GPIO_init();
|
||||
|
||||
steppers_init();
|
||||
|
||||
usb_disconnect(); // turn off USB
|
||||
|
||||
// init USART1
|
||||
UART_init(USART1);
|
||||
|
||||
// USB
|
||||
usbd_dev = USB_init();
|
||||
|
||||
// init ADC
|
||||
ADC_init();
|
||||
|
||||
// SysTick is a system timer with 1mc period
|
||||
SysTick_init();
|
||||
|
||||
|
||||
// switch_SPI(SPI2); // init SPI2
|
||||
// SPI_init();
|
||||
|
||||
@@ -171,11 +166,13 @@ int main(){
|
||||
init_ow_dmatimer();
|
||||
|
||||
// wait a little and then turn on USB pullup
|
||||
for (i = 0; i < 0x800000; i++)
|
||||
__asm__("nop");
|
||||
usb_connect(); // turn on USB
|
||||
// for (i = 0; i < 0x800000; i++)
|
||||
// __asm__("nop");
|
||||
|
||||
// init ADC
|
||||
ADC_init();
|
||||
ADC_calibrate_and_start();
|
||||
usb_connect(); // turn on USB
|
||||
while(1){
|
||||
usbd_poll(usbd_dev);
|
||||
if(usbdatalen){ // there's something in USB buffer
|
||||
@@ -192,7 +189,9 @@ int main(){
|
||||
OW_process(); // process 1-wire commands
|
||||
if(OW_DATA_READY()){
|
||||
OW_CLEAR_READY_FLAG();
|
||||
MSG("Ready!\n");
|
||||
#ifdef EBUG
|
||||
OW_printID(0, lastsendfun);
|
||||
#endif
|
||||
}
|
||||
process_stepper_motors(); // check flags of motors' timers
|
||||
if(Timer - Old_timer > 999){ // one-second cycle
|
||||
@@ -248,5 +247,3 @@ void print_time(sendfun s){
|
||||
s(' ');
|
||||
print_int(Timer, s);
|
||||
}
|
||||
|
||||
// D = dlmread('file')
|
||||
|
||||
@@ -36,16 +36,21 @@ uint8_t *read_buf = NULL; // buffer to read
|
||||
|
||||
uint8_t ow_data_ready = 0; // flag of reading OK
|
||||
|
||||
/**
|
||||
* fill buffer with zeros - read slots
|
||||
* @param N - amount of bytes to read
|
||||
*/
|
||||
uint8_t OW_Read(uint8_t N){
|
||||
uint8_t i;
|
||||
for(i = 0; i < N; i++)
|
||||
if(!OW_add_byte(0, 8, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
void OW_printID(uint8_t N, sendfun s){
|
||||
void putc(uint8_t c){
|
||||
if(c < 10)
|
||||
s(c + '0');
|
||||
else
|
||||
s(c + 'a' - 10);
|
||||
}
|
||||
int i;
|
||||
uint8_t *b = id_array[N].bytes;
|
||||
s('0'); s('x'); // prefix 0x
|
||||
for(i = 0; i < 8; i++){
|
||||
putc(b[i] >> 4);
|
||||
putc(b[i] & 0x0f);
|
||||
}
|
||||
s('\n');
|
||||
}
|
||||
|
||||
uint8_t ow_was_reseting = 0;
|
||||
@@ -59,22 +64,22 @@ void OW_process(){
|
||||
OW_State = OW_SEND_STATE;
|
||||
ow_was_reseting = 1;
|
||||
ow_reset();
|
||||
MSG("reset\n");
|
||||
//MSG("reset\n");
|
||||
break;
|
||||
case OW_SEND_STATE:
|
||||
if(!OW_READY()) return; // reset in work
|
||||
if(ow_was_reseting){
|
||||
if(!OW_get_reset_status()){
|
||||
MSG("error: no devices found\n");
|
||||
MSG("error: no 1-wire devices found\n");
|
||||
ow_was_reseting = 0;
|
||||
OW_State = OW_OFF_STATE;
|
||||
return;
|
||||
// OW_State = OW_OFF_STATE;
|
||||
// return;
|
||||
}
|
||||
}
|
||||
ow_was_reseting = 0;
|
||||
OW_State = OW_READ_STATE;
|
||||
run_dmatimer(); // turn on data transfer
|
||||
MSG("send\n");
|
||||
//MSG("send\n");
|
||||
break;
|
||||
case OW_READ_STATE:
|
||||
if(!OW_READY()) return; // data isn't ready
|
||||
@@ -84,7 +89,7 @@ void OW_process(){
|
||||
read_from_OWbuf(OW_start_idx, OW_wait_bytes, read_buf);
|
||||
}
|
||||
ow_data_ready = 1;
|
||||
MSG("read\n");
|
||||
//MSG("read\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -92,16 +97,28 @@ void OW_process(){
|
||||
/**
|
||||
* fill Nth array with identificators
|
||||
*/
|
||||
//uint8_t comtosend = 0;
|
||||
void OW_fill_ID(uint8_t N){
|
||||
if(N >= OW_MAX_NUM){
|
||||
MSG("number too big\n");
|
||||
return;
|
||||
}
|
||||
OW_Send(1, (uint8_t*)"\xcc\x33", 2);
|
||||
OW_Read(8); // wait for 8 bytes
|
||||
//OW_Send(1, (uint8_t*)"\xcc\x33", 2);
|
||||
OW_Send(1, (uint8_t*)"\x19", 1);
|
||||
// OW_Send(1, &comtosend, 1);
|
||||
// comtosend++;
|
||||
//OW_Send(1, (uint8_t*)"\xcc\xbe", 2);
|
||||
OW_add_read_seq(9); // wait for 9 bytes
|
||||
//OW_Send(0, (uint8_t*)"\xcc\x33\x10\x45\x94\x67\x7e\x8a", 8);
|
||||
read_buf = id_array[N].bytes;
|
||||
OW_wait_bytes = 8;
|
||||
OW_start_idx = 16;
|
||||
OW_start_idx = 0;
|
||||
/*
|
||||
OW_Send(0, (uint8_t*)"\x99\xee", 2);
|
||||
OW_wait_bytes = 2;
|
||||
OW_start_idx = 0;
|
||||
read_buf = id_array[N].bytes;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +131,6 @@ void OW_fill_ID(uint8_t N){
|
||||
*/
|
||||
uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen){
|
||||
uint8_t f = 1;
|
||||
ow_dma_on(); // reconfigure DMA1
|
||||
ow_data_ready = 0;
|
||||
// if reset needed - send RESET and check bus
|
||||
if(sendReset)
|
||||
|
||||
@@ -42,10 +42,12 @@ typedef struct{
|
||||
extern uint8_t ow_data_ready;
|
||||
#define OW_DATA_READY() (ow_data_ready)
|
||||
#define OW_CLEAR_READY_FLAG() do{ow_data_ready = 0;}while(0)
|
||||
|
||||
void OW_process();
|
||||
void OW_fill_ID(uint8_t N);
|
||||
|
||||
uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen);
|
||||
void OW_printID(uint8_t N, sendfun s);
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -66,15 +66,15 @@ uint8_t write_SPI(uint8_t *data, uint8_t len){
|
||||
//DBG("Write SPI.."); //return 1;
|
||||
uint8_t i;
|
||||
uint32_t tend = Timer + 10; // we will wait for end of previous transmission not more than 10ms
|
||||
//DBG("check\r\n");
|
||||
//DBG("check\n");
|
||||
while(!SPI_EOT_FLAG && Timer < tend); // wait for previous DMA interrupt
|
||||
if(!SPI_EOT_FLAG){
|
||||
DBG("SPI error: no EOT flag!\r\n");
|
||||
DBG("SPI error: no EOT flag!\n");
|
||||
return 0; // error: there's no receiver???
|
||||
}
|
||||
if(len > SPI_BUFFERSIZE) len = SPI_BUFFERSIZE;
|
||||
SPI_EOT_FLAG = 0;
|
||||
//DBG("OK\r\n");
|
||||
//DBG("OK\n");
|
||||
//read_end = Timer + 100; // we will wait for end of previous transmission not more than 0.1s
|
||||
for(i = 0; i < len; i++)
|
||||
SPI_TxBuffer[i] = data[i];
|
||||
@@ -102,13 +102,13 @@ uint8_t *read_SPI(uint8_t *data, uint8_t len){
|
||||
//DBG("read SPI.. "); //return NULL;
|
||||
uint8_t i;
|
||||
uint32_t tend = Timer + 100; // we will wait for end of previous transmission not more than 0.1s
|
||||
//DBG("check\r\n");
|
||||
//DBG("check\n");
|
||||
while((!SPI_EOT_FLAG || len != SPI_RxIndex) && Timer < tend);
|
||||
if(len != SPI_RxIndex){
|
||||
//DBG("SPI error: bad data length\r\n");
|
||||
//DBG("SPI error: bad data length\n");
|
||||
return NULL;
|
||||
}
|
||||
//DBG("OK\r\n");
|
||||
//DBG("OK\n");
|
||||
for(i = 0; i < len; i++){
|
||||
data[i] = SPI_RxBuffer[i];
|
||||
//print_int(SPI_RxBuffer[i], usb_send);
|
||||
|
||||
@@ -18,17 +18,28 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "stepper_motors.h"
|
||||
|
||||
// TODO: function "move motor to given position"
|
||||
|
||||
static uint8_t timers_activated[2] = {0, 0}; // flag of activated timers
|
||||
uint16_t Motor_period[2] = {10000, 10000}; // near 100 steps per second
|
||||
uint16_t Motor_period[2] = {1300, 1300}; // one step per 1.3ms
|
||||
uint32_t Turrets_pause = 2 * TURRETS_PAUSE_US / 1300; // pause in half-steps
|
||||
volatile uint8_t timer_flag[2] = {0,0};
|
||||
// amount of steps for each motor
|
||||
volatile uint32_t Motor_steps[5] = {0, 0, 0, 0, 0};
|
||||
// flag of active motor
|
||||
volatile uint8_t Motor_active[5] = {0, 0, 0, 0, 0};
|
||||
|
||||
/*
|
||||
* Wait flags: if non-zero, flag just decremented
|
||||
* (we need it to wait a little on turrets' fixed positions to omit Halls' histeresis)
|
||||
*/
|
||||
uint8_t waits[5] = {0,0,0,0,0};
|
||||
// Halls & end-switches values on previous step
|
||||
uint8_t lastpos[5] = {0,0,0,0,0};
|
||||
// number of position to move turret or stage, zero to move only for N given steps
|
||||
uint8_t move2pos[5] = {0,0,0,0,0};
|
||||
|
||||
/**
|
||||
* Setup stepper motors' timer Tim
|
||||
@@ -61,8 +72,10 @@ static void setup_timer(uint8_t N){
|
||||
timer_enable_irq(Tim, TIM_DIER_UIE); // update IRQ enable
|
||||
timer_enable_counter(Tim);
|
||||
timers_activated[N] = 1;
|
||||
#ifdef EBUG
|
||||
lastsendfun('3' + N);
|
||||
MSG(" timer\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,44 +96,141 @@ void steppers_init(){
|
||||
gpio_set_mode(MOTOR_TIM2_PORT, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, MOTOR_TIM2_PIN);
|
||||
// EN pins
|
||||
// WARNING! EN pins would be shortened to GND in case of overcurrent/overheating
|
||||
// so, they should be pull-up inputs in active mode & pull-down inputs in inactive mode!!!
|
||||
gpio_set_mode(MOTOR_EN_PORT, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, MOROT_EN_MASK);
|
||||
GPIO_CNF_INPUT_PULL_UPDOWN, MOTOR_EN_MASK);
|
||||
gpio_clear(MOTOR_EN_PORT, MOTOR_EN_MASK);
|
||||
// DIR pins
|
||||
gpio_set_mode(MOTOR_DIR_PORT, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, MOROT_DIR_MASK);
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, MOTOR_DIR_MASK);
|
||||
setup_timer(0);
|
||||
setup_timer(1);
|
||||
// Now setup Halls & end-switches
|
||||
SETUP_ESW();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test end-switches &
|
||||
* @param num - motor number
|
||||
* @param curpos - end-switches data for motor
|
||||
* @return 0 if we can move further, 1 if there's the end
|
||||
*/
|
||||
uint8_t test_stages_endpos(uint8_t num, uint8_t curpos){
|
||||
if(curpos == 0 || num < 3) return 0;
|
||||
// end-switches numbers for stages
|
||||
const uint8_t stage_plus[2] = {STAGE_CHECK(3, PLUS), STAGE_CHECK(4, PLUS)};
|
||||
const uint8_t stage_minus[2] = {STAGE_CHECK(3, MINUS), STAGE_CHECK(4, MINUS)};
|
||||
uint8_t negative_dir = 0;
|
||||
num -= 3; // convern num to index in arrays
|
||||
if((uint16_t)GPIO_IDR(MOTOR_EN_PORT) & MOTOR_EN_PIN(num)){ // negative direction
|
||||
negative_dir = 1;
|
||||
}
|
||||
if(stage_plus[num] == curpos){ // we are on "+" end-switch
|
||||
if(!negative_dir){ // and wanna move to "+"
|
||||
ERR("End-switch +\n");
|
||||
return 1;
|
||||
}
|
||||
}else if(stage_minus[num] == curpos){ // we are on "-" end-switch
|
||||
if(negative_dir){ // and wanna move to "-"
|
||||
ERR("End-switch -\n");
|
||||
return 1;
|
||||
}
|
||||
}else{ // error: WTF is going up? curpos != 2 or 1
|
||||
ERR("Wrong current position: ");
|
||||
print_int(curpos, lastsendfun);
|
||||
lastsendfun('\n');
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value of current Hall/end-switches position
|
||||
* (converted to normal uint8_t, 0 == none
|
||||
*/
|
||||
uint8_t check_ep(uint8_t num){
|
||||
switch (num){
|
||||
case 0:
|
||||
return CHECK_EP(0);
|
||||
break;
|
||||
case 1:
|
||||
return CHECK_EP(1);
|
||||
break;
|
||||
case 2:
|
||||
return CHECK_EP(2);
|
||||
break;
|
||||
case 3:
|
||||
return CHECK_EP(3);
|
||||
break;
|
||||
case 4:
|
||||
return CHECK_EP(4);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move motor Motor_number to User_value steps
|
||||
*/
|
||||
void move_motor(uint8_t num, int32_t steps){
|
||||
uint8_t curpos, negative_dir = 0;
|
||||
if(steps == 0) return;
|
||||
// check whether motor is moving
|
||||
if(Motor_active[num]){
|
||||
MSG("err: moving\r\n");
|
||||
ERR("moving\n");
|
||||
return;
|
||||
}
|
||||
#ifdef EBUG
|
||||
MSG("move ");
|
||||
lastsendfun('0' + num);
|
||||
MSG(" to ");
|
||||
print_int(steps, lastsendfun);
|
||||
MSG("\n");
|
||||
#endif
|
||||
if(steps < 0){
|
||||
negative_dir = 1;
|
||||
steps = -steps;
|
||||
}
|
||||
curpos = check_ep(num);
|
||||
lastpos[num] = curpos;
|
||||
if(negative_dir){
|
||||
gpio_set(MOTOR_DIR_PORT, MOTOR_DIR_PIN(num)); // set DIR bit to rotate ccw
|
||||
}else
|
||||
}else{
|
||||
gpio_clear(MOTOR_DIR_PORT, MOTOR_DIR_PIN(num)); // reset DIR bit
|
||||
Motor_steps[num] = steps << 4; // multiply by 16 to get usteps count
|
||||
}
|
||||
if(test_stages_endpos(num, curpos)) return; // error: we can't move
|
||||
// set all flags and variables
|
||||
Motor_steps[num] = steps; // we run in full-step mode!
|
||||
waits[num] = 0;
|
||||
Motor_active[num] = 1;
|
||||
gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(num)); // activate motor
|
||||
gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(num));
|
||||
}
|
||||
|
||||
void stop_motor(uint8_t num){
|
||||
if(!Motor_active[num]) return;
|
||||
#ifdef EBUG
|
||||
MSG("stop motor ");
|
||||
lastsendfun('0' + num);
|
||||
MSG("\r\n");
|
||||
MSG("\n");
|
||||
#endif
|
||||
gpio_clear(MOTOR_EN_PORT, MOTOR_EN_PIN(num));
|
||||
Motor_active[num] = 0;
|
||||
if(num < 3){ // this is a turret
|
||||
move2pos[num] = 0; // reset target position value
|
||||
if(check_ep(num) == 0){ // a turret is out of fixed position
|
||||
ERR("stop out of position\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wa cannot use EXTI because multiplexer doesn't allow simultaneous interrupts
|
||||
* handling on the same bits of different ports (e.g. PB7 & PD7)
|
||||
* So, I need to check registers' state before each step!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check flags set by timers & do next:
|
||||
* - decrease step counter if it isn't zero;
|
||||
@@ -132,15 +242,61 @@ void process_stepper_motors(){
|
||||
const uint32_t pins[] = {MOTOR_TIM1_PIN, MOTOR_TIM2_PIN};
|
||||
const uint8_t startno[] = {0, 3};
|
||||
const uint8_t stopno[] = {3, 5};
|
||||
uint8_t curpos;
|
||||
for(j = 0; j < 2; j++){
|
||||
if(timer_flag[j]){
|
||||
timer_flag[j] = 0;
|
||||
gpio_toggle(ports[j], pins[j]); // change clock state
|
||||
if(gpio_get(ports[j], pins[j])){ // positive pulse - next microstep
|
||||
for(i = startno[j]; i < stopno[j]; i++){ // check motors
|
||||
if(Motor_steps[i]) Motor_steps[i]--;
|
||||
else if(Motor_active[i]){ // stop motor - all done
|
||||
stop_motor(i);
|
||||
if(!gpio_get(ports[j], pins[j])){ // negative pulse - omit this half-step
|
||||
continue;
|
||||
}
|
||||
for(i = startno[j]; i < stopno[j]; i++){ // check motors
|
||||
if(Motor_active[i] == 0) continue; // inactive motor
|
||||
curpos = check_ep(i);
|
||||
if(Motor_steps[i] == 0){ // end of moving
|
||||
stop_motor(i); // even if this is a turret with move2pos[i]!=0 we should stop
|
||||
//(what if there's some slipping or so on?)
|
||||
}else{ // we should move further
|
||||
if(waits[i]){ // waiting for position stabilisation
|
||||
waits[i]--;
|
||||
if(waits[i]) continue; // there's more half-steps to skip
|
||||
lastpos[i] = curpos;
|
||||
// tell user current position
|
||||
MSG("position: ");
|
||||
print_int(curpos, lastsendfun);
|
||||
lastsendfun('\n');
|
||||
// turn on motor after pause
|
||||
gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(i));
|
||||
if(j == 1){ // this is a linear stage
|
||||
if(test_stages_endpos(i, curpos)){ // this is the end of way
|
||||
stop_motor(i);
|
||||
}
|
||||
}else{ // this is a turret
|
||||
if(move2pos[i]){ // we should move to specific position
|
||||
if(curpos == move2pos[i]){ // we are on position
|
||||
stop_motor(i);
|
||||
}else{ // add some steps to move to next position
|
||||
Motor_steps[i] += TURRETS_NEXT_POS_STEPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// check for overcurrent: if MOTOR_EN_PIN == 0
|
||||
if(!gpio_get(MOTOR_EN_PORT, MOTOR_EN_PIN(i))){
|
||||
ERR("overcurrent\n");
|
||||
stop_motor(i);
|
||||
continue;
|
||||
}
|
||||
if(lastpos[i] != curpos){ // transition process
|
||||
if(lastpos[i] == 0){ // come towards position
|
||||
waits[i] = Turrets_pause;
|
||||
// turn off motor while a pause
|
||||
gpio_clear(MOTOR_EN_PORT, MOTOR_EN_PIN(i));
|
||||
continue;
|
||||
}
|
||||
lastpos[i] = curpos;
|
||||
}
|
||||
Motor_steps[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,6 +304,7 @@ void process_stepper_motors(){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop timers; turn off motor voltage
|
||||
*
|
||||
@@ -165,7 +322,7 @@ void stop_timer(){
|
||||
/**
|
||||
* Sets motor period to user value & refresh timer
|
||||
* @param num - number of motor
|
||||
* @param period - period of one STEP in microseconds
|
||||
* @param period - period of one MICROSTEP in microseconds
|
||||
*/
|
||||
void set_motor_period(uint8_t num, uint16_t period){
|
||||
uint32_t Tim, N;
|
||||
@@ -175,6 +332,7 @@ void set_motor_period(uint8_t num, uint16_t period){
|
||||
case 3:
|
||||
Tim = TIM3;
|
||||
N = 0;
|
||||
Turrets_pause = 2 * TURRETS_PAUSE_US / period + 1; // pause in half-steps
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
@@ -185,7 +343,6 @@ void set_motor_period(uint8_t num, uint16_t period){
|
||||
MSG("err: bad motor");
|
||||
return;
|
||||
}
|
||||
period >>= 4; // divide by 4 to get 16usteps for one step
|
||||
if(period == 0) Motor_period[N] = 1;
|
||||
else Motor_period[N] = period;
|
||||
if(!timers_activated[N]) setup_timer(N);
|
||||
|
||||
@@ -24,6 +24,42 @@
|
||||
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
|
||||
// default pause to make sure that turret is on position
|
||||
#define TURRETS_PAUSE_US 30000
|
||||
// max amount of steps to add to turret for moving to next position
|
||||
#define TURRETS_NEXT_POS_STEPS 300
|
||||
|
||||
#ifndef CONCAT
|
||||
#define CONCAT(A, B) A ## B
|
||||
#endif
|
||||
|
||||
// check status of end-switches and Halls
|
||||
// Motor 0 == turret 0, PD0..PD3
|
||||
#define _CHECK_EP0 ((~GPIO_IDR(GPIOD)) & 0x0f)
|
||||
// Motor 1 == turret 1, PD4..PD6
|
||||
#define _CHECK_EP1 (((~GPIO_IDR(GPIOD)) >> 4) & 0x07)
|
||||
// Motor 2 == turret 2, PD7, PB6, PB7
|
||||
#define _CHECK_EP2 ((((~GPIO_IDR(GPIOD)) >> 7) & 0x01) | (((~GPIO_IDR(GPIOB))>> 6) & 0x03))
|
||||
// Motor 3 == long (VPHG, pupil stop) stage, PC7/PC8 (down/up)
|
||||
#define _CHECK_EP3 (((~GPIO_IDR(GPIOC)) >> 7) & 0x03)
|
||||
// Motor 4 == short (focus) stage, PC9/PA8 (down/up)
|
||||
#define _CHECK_EP4 ((((~GPIO_IDR(GPIOC)) >> 9) & 0x01) | (((~GPIO_IDR(GPIOA)) >> 8) & 0x01))
|
||||
// this macro returns end-switches & Hall status: 0 - not active, 1 - active
|
||||
#define CHECK_EP(X) CONCAT(_CHECK_EP, X)
|
||||
// end-switches for motors 3,4 (stage 1 and stage 2): stop when direction positive/negative
|
||||
#define EP3PLUS 2
|
||||
#define EP3MINUS 1
|
||||
#define EP4PLUS 2
|
||||
#define EP4MINUS 1
|
||||
#define STAGE_CHECK(N, DIR) CONCAT(EP ## N, DIR)
|
||||
|
||||
// setup ports: PA8, PB6, PB7, PC7..PC9, PD0..PD7
|
||||
#define SETUP_ESW() do{gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO8); \
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO6|GPIO7); \
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, (uint16_t)0x0380);\
|
||||
gpio_set_mode(GPIOD, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, (uint16_t)0xff); \
|
||||
}while(0)
|
||||
|
||||
void steppers_init();
|
||||
void process_stepper_motors();
|
||||
void move_motor(uint8_t num, int32_t steps);
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* implement mutexes for other type of MCU (which doesn't have strex & ldrex)
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
/* DMB is supported on CM0 */
|
||||
|
||||
@@ -42,7 +42,7 @@ uint32_t __strex(uint32_t val, volatile uint32_t *addr);
|
||||
typedef uint32_t mutex_t;
|
||||
|
||||
#define MUTEX_UNLOCKED 0
|
||||
#define MUTEX_LOCKED 1
|
||||
#define MUTEX_LOCKED 1
|
||||
|
||||
void mutex_lock(mutex_t *m);
|
||||
void mutex_unlock(mutex_t *m);
|
||||
|
||||
@@ -87,6 +87,7 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
||||
}else switch (command){
|
||||
case 'P':
|
||||
OW_fill_ID(0);
|
||||
//run_dmatimer();
|
||||
break;
|
||||
case 'x': // set period of TIM1 (motors 1..3)
|
||||
active_motor = 1;
|
||||
@@ -108,7 +109,7 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
||||
print_hex(onewire_addr, 8, s);
|
||||
}else
|
||||
P("1-wire error",s );
|
||||
P("\r\n", s);
|
||||
P("\n", s);
|
||||
break;*/
|
||||
case 'S': // single conversion
|
||||
doubleconv = 0;
|
||||
@@ -118,7 +119,7 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
||||
break;
|
||||
case 'A': // show ADC value
|
||||
//adc_start_conversion_direct(ADC1);
|
||||
P("\r\n ADC value: ", s);
|
||||
P("\n ADC value: ", s);
|
||||
for(j = 0; j < 8; j++){
|
||||
print_int(ADC_value[j], s);
|
||||
P("\t", s);
|
||||
@@ -153,9 +154,9 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
||||
print_ad_vals(s);
|
||||
break;
|
||||
case 'u': // check USB connection
|
||||
P("\r\nUSB ", s);
|
||||
P("\nUSB ", s);
|
||||
if(!USB_connected) P("dis", s);
|
||||
P("connected\r\n",s);
|
||||
P("connected\n",s);
|
||||
break;
|
||||
case 'M': // ADC monitoring ON
|
||||
ADC_monitoring = !ADC_monitoring;
|
||||
@@ -188,7 +189,7 @@ void prnt(uint8_t *wrd, sendfun s){
|
||||
|
||||
/*
|
||||
void newline(sendfun s){
|
||||
P("\r\n", s);
|
||||
P("\n", s);
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -301,26 +302,26 @@ void set_ADC_gain(int32_t v, sendfun s){
|
||||
*/
|
||||
void stepper_proc(int32_t v, sendfun s){
|
||||
if(active_motor > 4){
|
||||
P("wrong motor number\r\n", s);
|
||||
P("wrong motor number\n", s);
|
||||
return; // error
|
||||
}
|
||||
MSG("move ");
|
||||
lastsendfun('0' + active_motor);
|
||||
MSG(" to ");
|
||||
print_int(v, lastsendfun);
|
||||
MSG("\r\n");
|
||||
move_motor(active_motor, v);
|
||||
active_motor = 6;
|
||||
}
|
||||
|
||||
void set_timr(int32_t v, sendfun s){
|
||||
if(active_motor > 4){
|
||||
P("wrong motor number\r\n", s);
|
||||
P("wrong motor number\n", s);
|
||||
return; // error
|
||||
}
|
||||
if(v < 0 || v > 0xffff){
|
||||
MSG("Bad period!\n");
|
||||
active_motor = 6;
|
||||
return;
|
||||
}
|
||||
MSG("set period: ");
|
||||
print_int(v, lastsendfun);
|
||||
MSG("\r\n");
|
||||
MSG("\n");
|
||||
set_motor_period(active_motor, (uint16_t)v);
|
||||
active_motor = 6;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#define MSG(arg) prnt((uint8_t*)arg, lastsendfun)
|
||||
|
||||
#define ERR(arg) do{prnt((uint8_t*)"Error! ",lastsendfun); prnt((uint8_t*)arg, lastsendfun);}while(0)
|
||||
|
||||
typedef void (*sendfun)(uint8_t); // function to send a byte
|
||||
typedef void (*intfun)(int32_t, sendfun); // function to process entered integer value at end of input
|
||||
|
||||
|
||||
Reference in New Issue
Block a user