I am currently using Code Composer studio version 10. I am working with the following code for SPI implementation. I can't get the receiver code to work atm. I would like assistance to fix the problem with receive buffer.
`
#include <msp430.h>
#include <msp430g2553.h>
/**
*/
char data_send, data_recv;
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watch dog timer
P1SEL = BIT1 | BIT2 | BIT4;
P1SEL2 = BIT1 | BIT2 | BIT4;
UCA0CTL1 |= UCSWRST ;
UCA0CTL0 |= UCMSB + UCMST + UCSYNC+ UCCKPL;
UCA0CTL1 |= UCSSEL_2;
/**
*/
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = 0XAA;
data_send = UCA0TXBUF;
while (!(IFG2 & UCA0RXIFG));
data_recv = UCA0RXBUF;
P1OUT |= (BIT5);
return 0;
}
`
I have tried changing the values of the following code, which has not improved the problem.`
UCA0CTL1 |= UCSWRST ;
UCA0CTL0 |= UCMSB + UCMST + UCSYNC+ UCCKPL;
UCA0CTL1 |= UCSSEL_2;
`
Related
I have a problem with my system and I can't handle the problem. Problem is that ;
When I powered the system with DC volt (3.3 v) without debugging then I can't see anything on the receiver side (Arduino Uno as receiver). However if I use debugger[FET430 - UIF ] then I can see all of the characters on the receiver side.
This is my code :
#include <msp430.h>
#include "cc430x613x.h"
#include <msp430.h>
#include <string.h>
void terminal_write();
void UART_open();
void UART_close();
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
//__delay_cycles( 2 * 1e7);
while(1)
{
UART_open();
printf("system working\r\n");
terminal_write("AT\r\n");
__delay_cycles(5000000);
//_bis_SR_register(LPM3_bits + GIE);
UART_close();
}
}
void terminal_write(char *info)
{
unsigned int i;
unsigned int len = strlen(info) ;
for(i=0;i<len;i++)
{
UCA0TXBUF=info[i];
__delay_cycles(10000);
}
}
void UART_open(){
P1SEL |= BIT5 + BIT6;
//UART Settings
UCA0CTL1 |= UCSWRST;
UCA0CTL1 |= UCSSEL0 ; // ACLK
UCA0BR0=3; //UCA0BR0 = 3 ; //32Khz / 9600 –>> 3
UCA0BR1=0; //UCA0BR1=0; // BAUD 9600; ( UCABR1 * 256 ) + UCABR0 = UCABRx see "slau259e.pdf"
UCA0MCTL=6 ; // see "slau259e.pdf" page 602 //
//UCA0MCTL =| BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
// |------- UCBRFx --------------|----UCBRSx----------|UCOS16|
// for 9600 baudrate at 32kHz UCBRFx = 0 , UCBRSx = 3 , UCOS16 = 0
// | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
// 0b00000110 = 0x06 = 6
UCA0CTL1 &=~ UCSWRST;//
UCA0CTL1 |= UCDORM;
}
void UART_close(){
P1SEL &= ~(BIT5 + BIT6);
UCA0CTL1 |= UCSWRST;
UCA0CTL1 &=~ UCDORM;
}
Beside if I use DC power then the system consumption is about 450-550 uA. If I use debugger then the DC power consumption is raises to about 4.8 mA . Also if I only use the debugger [powered with debugger voltage without using any external DC supply] then system can't handle the communication properly.
If there is a solutiion I'll very appreciate.
Firtina, is it possible that you are only connecting the DC power supply to the analog voltage input (AVSS) and not the digital input (DVCC)? If so, then my explanation is the JTAG tool is supplying the CCF6137 chip with proper power, but when disconnected the chip doesn't have power to the digital side. If this is the case, then try connecting the DC power supply to both AVSS and DVCC pins and test again without the JTAG tool. Also, check that you are giving the chip proper ground.
I am working with mbed, the LPC1768. The serial input to the mbed is a unsigned character array which is not null-terminated. I don't get anything with getc(), how to get the input?
the null character is 0 so if you need get it u can using a Buffer Counter or a ovf variable to detect received a character!!
Config your UART0,1 by this Setting:
comment UART0 or UART1 if not use it!
so u can select UARTs with #define in: option->C/C++->Define:__UART0 or __UART1
void SER_Init (void) {
#ifdef __UART0 /* UART0 */
LPC_SC->PCONP |= ((1 << 3) | (1 << 15)); /* enable power to UART0 & IOCON */
LPC_PINCON->PINSEL0 |= (1 << 4); /* Pin P0.2 used as TXD0 */
LPC_PINCON->PINSEL0 |= (1 << 6); /* Pin P0.3 used as RXD0 */
#else /* UART1 */
LPC_SC->PCONP |= ((1 << 4) | (1 << 15)); /* enable power to UART1 & IOCON */
LPC_PINCON->PINSEL4 |= (2 << 0); /* Pin P2.0 used as TXD1 */
LPC_PINCON->PINSEL4 |= (2 << 2); /* Pin P2.1 used as RXD1 */
#endif
UART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
UART->DLL = 9; /* 115200 Baud Rate # 25.0 MHZ PCLK*/
UART->FDR = 0x21; /* FR 1,507, DIVADDVAL=1, MULVAL=2 */
UART->DLM = 0; /* High divisor latch = 0 */
UART->LCR = 0x03; /* DLAB = 0 */
}
------> and use this func. for Get Character:
/*----------------------------------------------------------------------------
Read character from Serial Port (blocking read)
*----------------------------------------------------------------------------*/
int SER_GetChar (void) {
while (!(UART0->LSR & 0x01));
return (UART0->RBR);
}
I'm trying to achieve 10MSPS as documented in STM32F30x ADC modes and application under the section Dual interleaved mode.
Firstly, i tried to use single DMA. I configured the DMA1 Channel1 to read from ADC1&2 Common data register. It worked but i could only achieve a sample rate of 8.47MSPS. Beyond that limit, ADC1 starts to overrun.
(Register ADC1_2->CCR: MULT=0x07, MDMA=0x02, DELAY=0x04) Considering the DMA reading the common data register after the slave adc ends its conversion, the problem seems reasonable at high sample rates.
So i decided to use 2 DMAs. One for each ADC:
DMA1 Channel1 copies from ADC1->DR to SRAM
DMA2 Channel1 copies from ADC2->DR to SRAM
(Register ADC1_2->CCR: MULT=0x07, MDMA=0x00, DELAY=0x04)
This configuration also worked but again up to 8MSPS. Above that rate, ADC2 starts to overrun. I cannot understand why ADC2 overruns. I expected that this setup would work.
When i run ADC1 & ADC2 in independent mode with DMA configuration above, everything seems to work fine. No overruns, both ADC samples at 5.1MSPS but independently.
One question: What happens when both ADCs run in independent mode and triggered from the same source (e.g. TIM2) but ADC1 is triggered at the rising edge and ADC2 is triggered at the falling edge of the clock ? Would it work? This is the next thing i will try.
The MCU i work with is STM32F303CB.
ADC sampling times were 1.5 Cycles.
Any advice will be appreciated.
Edit: I have provided a minimal sample code that runs on STM32F3 Discovery with an 8 MHz Crystal. Program directly jumps to main()
// main.c
#include "stm32f30x.h"
#define DUALDMA
void sysinit();
void clockconfig();
void delay(int d);
void timerinit();
void adcinit();
void dmainit();
void dualdmainit();
int main(){
sysinit();
clockconfig();
timerinit();
#ifdef DUALDMA
dualdmainit();
#else
dmainit();
#endif
adcinit();
RCC->AHBENR |= RCC_AHBENR_GPIOEEN; // GPIOE enable
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // GPIOA enable
GPIOE->MODER = 0x55555555; // GPIOE -> output
GPIOA->MODER |= 0x0000FFFF;// GPIOA -> analog
// Reset SRAM memory area
for(int i = 0;i<1024*4;i+=4){
*((uint32_t*)(0x20000800+i)) = 0;
}
// Blink LEDs
while(1){
GPIOE->ODR = 0xFFFF;
delay(1000);
GPIOE->ODR = 0x00FF;
delay(1000);
}
}
void delay(int d){
// Dummy delay
int l = d*1000;
for(int i = 0;i<l;i++);
}
void sysinit(){
//STM32F303 reset state
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= 0x00000001U;
/* Reset CFGR register */
RCC->CFGR &= 0xF87FC00CU;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE bits */
RCC->CFGR &= 0xFF80FFFFU;
/* Reset PREDIV1[3:0] bits */
RCC->CFGR2 &= 0xFFFFFFF0U;
/* Reset USARTSW[1:0], I2CSW and TIMs bits */
RCC->CFGR3 &= 0xFF00FCCCU;
/* Disable all interrupts */
RCC->CIR = 0x00000000U;
SCB->VTOR = 0x08000000; /* Vector Table Relocation in Internal FLASH */
}
void adcinit(){
RCC->AHBENR |= RCC_AHBENR_ADC12EN; // Enable ADC clock
RCC->CFGR2 |= RCC_CFGR2_ADCPRE12_4;// ADC clock prescaler = 1
ADC1->CFGR |= ADC_CFGR_EXTEN_0; // Trigger on rising edge
ADC1->CFGR |= ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1; // TIM1 TRGO2
ADC1->SQR1 |= ADC_SQR1_SQ1_0 ; // ch 1
ADC1->CFGR |= ADC_CFGR_OVRMOD; // Stop on overrun
ADC1->CFGR |= ADC_CFGR_DMAEN; // DMA enable
ADC1->CR &= ~(ADC_CR_ADVREGEN_1 | ADC_CR_ADVREGEN_0); // Enable VREG
ADC1->CR |= ADC_CR_ADVREGEN_0;
ADC1->CR |= ADC_CR_ADEN;
while( (ADC1->ISR & ADC_ISR_ADRD) == 0 );
ADC2->SQR1 |= ADC_SQR1_SQ1_0 ; // ch 1
ADC2->CFGR |= ADC_CFGR_DMAEN;
ADC2->CR &= ~(ADC_CR_ADVREGEN_1 | ADC_CR_ADVREGEN_0);
ADC2->CR |= ADC_CR_ADVREGEN_0;
ADC2->CR |= ADC_CR_ADEN;
while( (ADC1->ISR & ADC_ISR_ADRD) == 0 );
ADC1_2->CCR |= ADC12_CCR_DELAY_2 ; // Delay = 4, 5 Cycles
#ifndef DUALDMA
ADC1_2->CCR |= ADC12_CCR_MDMA_1; // If single DMA is selected, configure MDMA bits for 12 bits
#endif
ADC1_2->CCR |= ADC12_CCR_MULTI_2 | ADC12_CCR_MULTI_1 | ADC12_CCR_MULTI_0; // Interleaved mode
}
void dmainit(){
// DMA config for Single DMA, 32 bits
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CPAR = (uint32_t)&ADC1_2->CDR;
DMA1_Channel1->CMAR = 0x20000800;
DMA1_Channel1->CNDTR = 1024;
DMA1_Channel1->CCR = DMA_CCR_EN | DMA_CCR_MINC | DMA_CCR_MSIZE_1 | DMA_CCR_PSIZE_1;
//DMA1_Channel1->CCR = DMA_CCR_EN | DMA_CCR_MINC ;
}
void dualdmainit(){
// DMA config for DUAL DMA, 16bits
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // DMA1 Enable
RCC->AHBENR |= RCC_AHBENR_DMA2EN; // DMA2 Enable
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
DMA1_Channel1->CMAR = 0x20000800;
DMA1_Channel1->CNDTR = 1024;
DMA1_Channel1->CCR = DMA_CCR_EN | DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0;
DMA2_Channel1->CPAR = (uint32_t)&ADC2->DR;
DMA2_Channel1->CMAR = 0x20000800+1024*2;
DMA2_Channel1->CNDTR = 1024;
DMA2_Channel1->CCR = DMA_CCR_EN | DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0;
}
void timerinit(){
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // Enable TIM1
TIM1->CR2 |= TIM_CR2_MMS2_1; // Update event selected as TRGO2
TIM1->PSC = 0;
TIM1->ARR = 0x0d; // 5 MHz (72 MHz / 14 )
TIM1->CR1 |= TIM_CR1_CEN;
}
void clockconfig(){
// External oscillator (HSE): 8MHz
RCC->CR |= RCC_CR_HSEON; // Enable HSE
while( (RCC->CR & RCC_CR_HSERDY) == 0 );
RCC->CFGR |= RCC_CFGR_PLLMULL9; // PLL MUL = x9
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 Prescaler = 2
RCC->CFGR |= RCC_CFGR_PLLSRC; // PLL source = HSE
FLASH->ACR |= FLASH_ACR_LATENCY_1; // Two wait states
RCC->CR |= RCC_CR_PLLON; // Enable and wait PLL
while( (RCC->CR & RCC_CR_PLLRDY) == 0 );
RCC->CFGR |= RCC_CFGR_SW_PLL; // Select PLL as system clock
}
Scatter file:
LR_IROM1 0x08000000 0x00020000 { ; load region size_region
ER_IROM1 0x08000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM2 0x10000000 0x00000200 { ; RW data
.ANY (+RW +ZI)
}
}
You cant do it this way. You need to use only one DMA channel and both samples are transmitted in one 32 bit DMA transaction.
In 6 bits mode I have archived more than 18MSPS
I do not know how to program it using HAL as I personally do only the bare register approach
There is a hardware problem as well (read the errata) and sometimes in >8bit modes the transfer does not work properly.
For dual DMA you need to:
Prevent any core accesses to the SRAM memory by placing the stack and the variables (except the ADC buffers) in the CCM RAM or suspending any core activity by entering the sleep mode.
I am currently trying to use an ATtiny84 to communicate with an RTC (DS1305) through SPI to make an buzzer vibrate every variable amount of time. I've been trying to set alarm0 on the DS1305. However, the 84 does not "technically" have SPI. It has USI which can be programmed to be like SPI. I was wondering if any of you could review my code/ board connections and let me know if you see any problems. The current problem is that I cannot get any communication going through SPI and I am having trouble finding what the issue could be.
Current board connections:
ATtiny84 | DS1305
MOSI ------ DI
MISO ------ DO
USCLK ---- CLK
Datasheets:
Attiny84
DS1305
/*
* Atmel_Jolt_Code.c
*
* Created: 11/28/2018 10:44:30 PM
* Author : Nick Hulsey
*/
#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>
#include <util/delay.h>
//variables for SPI
#define SPI_DDR_PORT DDRA
#define CE_PIN DDA3 //I ADDED *****
#define DO_DD_PIN DDA5 // SHOULD WE
#define DI_DD_PIN DDA6 // THEM FLIP
#define USCK_DD_PIN DDA4
#define SPI_MODE0 0x00
#define SPI_MODE1 0x04
#define MOTOR_PIN DDA7 //I ADDED *****
void SPI_begin();
void setDataMode(uint8_t spiDataMode);
uint8_t transfer(uint8_t spiData);
void flipLatch(uint8_t on);
int main(void)
{
SPI_begin();
setDataMode(SPI_MODE1);
DDRA |= (1 << MOTOR_PIN);
//**startup**
uint8_t status_register = 0x10;
uint8_t control_register = 0x8F;
uint8_t control_byte = 0x05;
uint8_t alarm_registers[] = {0x8A, 0x89, 0x88, 0x87};
//set control
flipLatch(1);
transfer(control_register);
transfer(0);
flipLatch(0);
flipLatch(1);
transfer(control_register);
transfer(control_byte);
flipLatch(0);
//set alarm:
for (int i = 0; i < 4; i++){
flipLatch(1);
transfer(alarm_registers[i]);
transfer(0x80); //0b10000000
flipLatch(0);
}
//THIS MIGHT NEED WORK
//GIMSK |= (1 << PCIE1);//set external interrupt (A1)
PCMSK0 |= (1 << PCINT1);
sei();
while (1) //our main loop
{
//reading the flag from the status register
uint8_t status = transfer(status_register);
if(status == 0x01){//if alarm 0 has been flagged
PORTA ^= (1 << MOTOR_PIN);
_delay_ms(100);
}
}
}
//if A1 has changed state at all this function will fire
ISR(PCINT1_vect){
PORTA ^= (1 << MOTOR_PIN);//invert motor power
_delay_ms(100);
}
void SPI_begin(){
USICR &= ~((1 << USISIE) | (1 << USIOIE) | (1 << USIWM0));//Turn off these bits
USICR |= (1 << USIWM0) | (1 << USICS1) | (1 << USICLK);//Turn on these bits
//REVIEW THIS PAGE 128
//external,positive edge software clock
//What does this mean
SPI_DDR_PORT |= 1 << USCK_DD_PIN; // set the USCK pin as output
SPI_DDR_PORT |= 1 << DO_DD_PIN; // set the DO pin as output
SPI_DDR_PORT |= 1 << CE_PIN;// ******** I ADDED
SPI_DDR_PORT &= ~(1 << DI_DD_PIN); // set the DI pin as input
}
void setDataMode(uint8_t spiDataMode)
{
if (spiDataMode == SPI_MODE1)
USICR |= (1 << USICS0);
else
USICR &= (1 << USICS0);
}
//returns values returned from the IC
uint8_t transfer(uint8_t spiData)
{
USIDR = spiData;
USISR = (1 << USIOIF); // clear counter and counter overflow interrupt flag
//ATOMIC_BLOCK(ATOMIC_RESTORESTATE) // ensure a consistent clock period
//{
while ( !(USISR & (1 << USIOIF)) ) USICR |= (1 << USITC);
//}
return USIDR;
}
void flipLatch(uint8_t on){
if (on == 1)
PORTA |= (1 << CE_PIN);
else
PORTA &= ~(1 << CE_PIN);
}
Trying to get an ATmega162 USART up and running. This code does exactly what I expect it to:
#define F_CPU 14745600UL
#define UBRR_1 F_CPU / 16 / 9600 - 1
#define UBRR_2 F_CPU / 16 / 31250 - 1
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
int main(){
uint16_t ubrr1 = UBRR_1;
UBRR0H = (uint8_t)(ubrr1 >> 8);
UBRR0L = (uint8_t)ubrr1;
UCSR0B = _BV(TXEN0);
UCSR0C = _BV(URSEL0) | _BV(UCSZ00) | _BV(UCSZ01);
uint16_t ubrr2 = UBRR_2;
UBRR1H = (uint8_t)(ubrr2 >> 8);
UBRR1L = (uint8_t)ubrr2;
UCSR1B = _BV(RXEN1);
UCSR1C = _BV(URSEL1) | _BV(UCSZ10) | _BV(UCSZ11);
DDRB = _BV(PB0) | _BV(PB1);
PORTB |= _BV(PB0);
while (1){
PORTB ^= _BV(PB0);
_delay_ms(50);
// byte received on usart 1
if ((UCSR1A & _BV(RXC1)) != 0){
// usart 0 ready to write
if ((UCSR0A & _BV(UDRE0)) != 0){
uint8_t b = UDR1;
UDR0 = b;
}
}
}
return 0;
}
That is, initializes the two USARTs at different baud rates, reads from USART1 and writes to USART0. Works great. Yes, I know that _delay_ms() is messing with the timing, but it works fine for this example. Now, as soon as I enable the RX interrupt on USART1 and add the appropriate vector, the main loop stops running (the LED isn't blinking, at least):
#define F_CPU 14745600UL
#define UBRR_1 F_CPU / 16 / 9600 - 1
#define UBRR_2 F_CPU / 16 / 31250 - 1
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
int main(){
uint16_t ubrr1 = UBRR_1;
UBRR0H = (uint8_t)(ubrr1 >> 8);
UBRR0L = (uint8_t)ubrr1;
UCSR0B = _BV(TXEN0);
UCSR0C = _BV(URSEL0) | _BV(UCSZ00) | _BV(UCSZ01);
uint16_t ubrr2 = UBRR_2;
UBRR1H = (uint8_t)(ubrr2 >> 8);
UBRR1L = (uint8_t)ubrr2;
UCSR1B = _BV(RXEN1);
UCSR1C = _BV(URSEL1) | _BV(UCSZ10) | _BV(UCSZ11);
DDRB = _BV(PB0) | _BV(PB1);
// enable usart1 rx interrupt
UCSR1B |= _BV(RXCIE1);
PORTB |= _BV(PB0);
// enable interrupts
sei();
while (1){
PORTB ^= _BV(PB0);
_delay_ms(50);
}
return 0;
}
ISR(USART1_RXC_vect){
uint8_t byte = UDR1;
if ((UCSR0A & _BV(UDRE0)) != 0){
UDR0 = byte;
}
}
The weirdest part is that it's not the sei(); and UCSR1B |= _BV(RXCIE1); lines that make the program stop working -- it's the existence of the ISR. As soon as I comment out that function, the main loop executes normally. Did I miss a flag somewhere?
It's possible this has been caused by the M161C fuse bit (in the extended fuse byte) becoming programmed. This puts the ATmega162 into ATmega161 compatibility mode which causes the device to have a different layout of the interrupt vector table (which the compiler won't know about.) See enter link description here Page 57 for the details. You could test this by compiling with -mmcu=atmega161 and seeing if it fixes the problem.
The other thing which would cause similar behaviour is if this code is run on an (almost identical-looking) ATmega16 instead of an ATmega162 as the UDR1 register is in a different place in the IO register map, meaning that the RXC interrupt flag would never get cleared and the handler would re-enter forever. You can check the register values the compiler is using by disassembling with avr-objdump.