unsigned short USART_Write(USART * serial, unsigned char * buf, unsigned short num_bytes) { unsigned short written; USART_UdeInterrupt_Disable(serial->port); written = RingBufferAdd(&serial->tx_buffer, buf, num_bytes); if (serial->use_rs485) { // assert if necessary *(serial->port.GPIO) |= serial->port.txen_pin_bm; USART_TransmitMode(serial, true); USART_TxdInterrupt_Enable(serial->port); } USART_UdeInterrupt_Enable(serial->port); return written; }
unsigned short USART_Write(USART * serial, unsigned char * buf, unsigned short num_bytes) { unsigned short written; unsigned char tempCTRLA = serial->port.usart_port->CTRLA; tempCTRLA = (tempCTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_OFF_gc; serial->port.usart_port->CTRLA = tempCTRLA; written = RingBufferAdd(&serial->tx_buffer, buf, num_bytes); #ifdef USE_RS485 if (serial->use_rs485) { serial->port.gpio_port->OUTSET = serial->port.txen_pin_bm; } #endif tempCTRLA = serial->port.usart_port->CTRLA; tempCTRLA = (tempCTRLA & ~USART_DREINTLVL_gm) | USART_DREINTLVL_LO_gc; serial->port.usart_port->CTRLA = tempCTRLA; return written; }
int main(void) { InitClock(); SerialInit(); RingBufferInit(&location_buffer, 4, locations); PORTC.DIRSET = 0xF3; PORTE.DIRSET = 0xFF; PORTD.DIRSET = 0x33; PORTB.DIRCLR = 0xFF; /* PortB all inputs */ /* Timers */ //x_axis.step_timer = &TCC1; x_axis.pwm_timer = &TCC0; /* Limit Switches */ x_axis.limit_switch_port = &PORTB; x_axis.limit_switch_mask = (1<<0); /* PORTB.0 */ /* DIR ports (for inverting the stepper motor driver polarity) */ x_axis.sign_select_port = &PORTC; x_axis.sign_switch_mask1 = 0x20; /* PORTC.5 */ x_axis.sign_switch_mask2 = 0x10; /* PORTC.4 */ /* PWM outputs: outputs will be 90 degrees out of phase */ x_axis.phase_pwm_cmp1 = &(TCC0.CCB); x_axis.phase_pwm_cmp2 = &(TCC0.CCA); x_axis.compare_mask = TC0_CCBEN_bm | TC0_CCAEN_bm; /* Power Controls change the period: a longer period means longer off time and lower duty cycle */ //x_axis.axis_idle_power = 60; x_axis.axis_run_power = 31; /* The minimum period of the PWM update timer/counter */ /* Stepper motor tick period = 32 * min_period / 16000000 */ //x_axis.min_period = 15; AxisInit (&x_axis); //y_axis.step_timer = &TCD1; y_axis.pwm_timer = &TCD0; y_axis.limit_switch_port = &PORTB; y_axis.limit_switch_mask = (1<<1); /* PORTB.1 */ y_axis.sign_select_port = &PORTD; y_axis.sign_switch_mask1 = 0x20; y_axis.sign_switch_mask2 = 0x10; y_axis.phase_pwm_cmp1 = &(TCD0.CCB); y_axis.phase_pwm_cmp2 = &(TCD0.CCA); y_axis.compare_mask = TC0_CCBEN_bm | TC0_CCAEN_bm; //y_axis.axis_idle_power = 60; y_axis.axis_run_power = 31; //y_axis.min_period = 15; AxisInit (&y_axis); //z_axis.step_timer = &TCE1; z_axis.pwm_timer = &TCE0; z_axis.limit_switch_port = &PORTB; z_axis.limit_switch_mask = (1<<2); /* PORTB.2 */ z_axis.sign_select_port = &PORTE; z_axis.sign_switch_mask1 = 0x20; /* PORTE.5 */ z_axis.sign_switch_mask2 = 0x10; /* PORTE.4 */ z_axis.phase_pwm_cmp1 = &(TCE0.CCD); z_axis.phase_pwm_cmp2 = &(TCE0.CCC); z_axis.compare_mask = TC0_CCDEN_bm | TC0_CCCEN_bm; //z_axis.axis_idle_power = 60; z_axis.axis_run_power = 31; /* 33 unique waveform values: 0 (ground) to 33 (3.3v) */ //z_axis.min_period = 15; AxisInit (&z_axis); PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; // Fire up the timer for incrementing/decrementing steps TC0_t * step_timer = &TCC1; step_timer->CTRLB = TC_WGMODE_SS_gc; /* Overflow every 1 ms: 16Mhz / (64 * 250) = 1ms */ step_timer->PER = 250; step_timer->CTRLA = TC_CLKSEL_DIV64_gc; step_timer->CTRLFSET = TC_CMD_RESTART_gc; /* Enable the step overflow interrupt */ step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // To Disable: axis->step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; char task = 0; sei(); while(1) { //PORTE.OUTTGL = 0x02; //_delay_ms (10); //SerialData * s = SerialDataTransmitStruct(); //if (s != 0) //{ // s->transmit_data[0] = 'a'; // s->transmit_data[1] = 'b'; // s->transmit_data[2] = 'c'; // SerialTransmit(s, 0x00, 3); //} SerialData * s = SerialDataAvailable(); if (s != 0) { switch (s->receive_data[0]) { case 0x88: // Reset everything (all axis back to limit switches) { task = TASK_LIMIT_SWITCH_Y; x_axis.state = 1; y_axis.state = 1; z_axis.state = 1; s->transmit_data[0] = 0x88; SerialTransmit (s, 0x00, 1); // Transmit to master device break; } case 0x77: // Ping (and location/status information) { s->transmit_data[0] = 0x77; // TODO: find a better way to do this step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer int32_t x = AxisGetCurrentPosition(&x_axis); int32_t y = AxisGetCurrentPosition(&y_axis); int32_t z = AxisGetCurrentPosition(&z_axis); step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer s->transmit_data[1] = x & 0xFF; x = x >> 8; s->transmit_data[2] = x & 0xFF; x = x >> 8; s->transmit_data[3] = x & 0xFF; x = x >> 8; s->transmit_data[4] = x & 0xFF; s->transmit_data[5] = y & 0xFF; y = y >> 8; s->transmit_data[6] = y & 0xFF; y = y >> 8; s->transmit_data[7] = y & 0xFF; y = y >> 8; s->transmit_data[8] = y & 0xFF; s->transmit_data[9] = z & 0xFF; z = z >> 8; s->transmit_data[10] = z & 0xFF; z = z >> 8; s->transmit_data[11] = z & 0xFF; z = z >> 8; s->transmit_data[12] = z & 0xFF; uint8_t status_bits = 0; if (IsMoving (&x_axis)) { status_bits |= 0x01; } if (IsMoving (&y_axis)) { status_bits |= 0x02; } if (IsMoving (&z_axis)) { status_bits |= 0x04; } s->transmit_data[13] = status_bits; //step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer buffer_lock = 1; s->transmit_data[14] = RingBufferCount(&location_buffer); buffer_lock = 0; //step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer //s->transmit_data[14] = location_buffer_size; SerialTransmit (s, 0x00, 15); // Transmit to master device break; } case 0x32: // Set Position + Speed { Location_t l; /* Bytes 1:2 are time in milliseconds */ l.time = decode_uint16_t(&(s->receive_data[1])); /* Bytes 3:14 are position */ l.x = decode_uint32_t(&(s->receive_data[3])); l.y = decode_uint32_t(&(s->receive_data[7])); l.z = decode_uint32_t(&(s->receive_data[11])); // Add the new location to the buffer //step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer buffer_lock = 1; if (!RingBufferIsFull(&location_buffer)) { RingBufferAdd(&location_buffer, l); } //if (location_buffer_size < 1) //{ // nextLocation = l; // location_buffer_size++; //} s->transmit_data[1] = RingBufferCount(&location_buffer); buffer_lock = 0; //step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer s->transmit_data[0] = 0x32; //s->transmit_data[1] = location_buffer_size; SerialTransmit(s, 0x00, 2); break; } } } else if (task == TASK_LIMIT_SWITCH_Y) { uint8_t v = LimitSwitchHelper(&x_axis); v &= LimitSwitchHelper(&y_axis); v &= LimitSwitchHelper(&z_axis); if (v) { task = 0; } } }