I installed the ftdilib and I am trying to compile this code:
/* hello-ftdi.c: flash LED connected between CTS and GND.
This example uses the libftdi API.
Minimal error checking; written for brevity, not durability. */
#include <stdio.h>
#include <ftdi.h>
#define LED 0x08 /* CTS (brown wire on FTDI cable) */
int main()
{
unsigned char c = 0;
struct ftdi_context ftdic;
/* Initialize context for subsequent function calls */
ftdi_init(&ftdic);
/* Open FTDI device based on FT232R vendor & product IDs */
if(ftdi_usb_open(&ftdic, 0x0403, 0x6001) < 0) {
puts("Can't open device");
return 1;
}
/* Enable bitbang mode with a single output line */
ftdi_enable_bitbang(&ftdic, LED);
/* Endless loop: invert LED state, write output, pause 1 second */
for(;;) {
c ^= LED;
ftdi_write_data(&ftdic, &c, 1);
sleep(1);
}
}
but there is error: ftdi_enable_bitbang was not declared in this scope
This is the only error.
Why does this keep to pop out?
One quick look into the current version of ftdi.h shows there is no declaration for ftdi_enable_bitbang. ftdi_enable_bitbang has been removed after being deprecated for two years. Use ftdi_set_bitmode instead.
Related
I have build a prototype board with a STM8L, and I want it to be used and configured as a SPI slave. I am testing it with a raspberry pi as master.
I use the lib provided by ST called "STM8 Standard Peripherals Library" for this, but the documentation is very poor and doesn't expain how to do this...
I can send data from the Raspberry Pi with no issue and receive it on the STM8 but I can't send back any data to the raspberry from the STM8 on MISO.
Is anybody known how I can send back some data to the Raspberry Pi master? Where is my mistake?
Here is the main code:
void main(void)
{
// GPIO
GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
CLK_Config();
// Set the MOSI and SCK at high level
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5, ENABLE);
SPI_DeInit(SPI1);
SPI_Init(SPI1, SPI_FirstBit_LSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_2Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);
SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);
// Enable SPI
SPI_Cmd(SPI1, ENABLE);
/* Infinite loop */
while (1)
{
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// SPI polling
if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
GPIO_ToggleBits(GPIOA, GPIO_Pin_7);
uint8_t data = SPI_ReceiveData(SPI1);
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// I can't send back data here, it doesn't work
SPI_SendData(SPI1, 0xFA);
uint8_t test = SPI1->DR;
GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}
}
}
static void CLK_Config(void)
{
/* Select HSE as system clock source */
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
/*High speed external clock prescaler: 1*/
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
{}
/* Enable SPI clock */
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}
And the RPi simple code:
#include <iostream>
#include <wiringPi.h>
#include <wiringPiSPI.h>
using namespace std;
int main()
{
wiringPiSetup();
wiringPiSPISetup(0, 50000);
unsigned char data[] = {0x5A};
wiringPiSPIDataRW(0, data, 2);
std::cout<<data<<std::endl;
return 0;
Thank you for your help! :)
Edit: I think the mistake is in uC code because the spi data register still contain the data sent by the master after I read it. I can't change it even by trying to write directly in the register.
Also: is it normal that the device only contain one data register for SPI? How is it supposed to be full duplex if it haven't one for MOSI (Rx) and one for MISO(Tx)? I think there is something I don't understand about SPI. I am not very experienced with this serial protocol. I mainly used I2C before.
SPI requires the master to provide the clock. If you want the slave to send something - your master
has to send some dummuy data to generate the clock for the slave.
I finaly found where were my mistakes.
First, I forgot to configure a pullup resistor on the MISO pin:
// Set the MOSI and SCK at high level
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);
Next, the SPI config were wrong. The Rpi was in MSB and the STM8 in LSB, and phase was on the second edge when it needed to be on the first edge:
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);
Finaly, not a mistake but a not optimal way to test: I were sending 0x81 with the master, but it is symetric in binary (0b10000001). I should have sent some asymetric message, for example 0x17 (0b00010111).
And the complete STM8 code:
#include "stm8l15x.h"
#include "stm8l15x_it.h" /* SDCC patch: required by SDCC for interrupts */
static void CLK_Config(void);
void Delay(__IO uint16_t nCount);
void main(void)
{
// GPIO
GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
CLK_Config();
// Set the MOSI and SCK at high level (I added MOSI)
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);
SPI_DeInit(SPI1);
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);
SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);
// Enable SPI
SPI_Cmd(SPI1, ENABLE);
/* Infinite loop */
while (1)
{
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// SPI polling
if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {
// maybe this line is not necessary, I didn't have the time to test without it yet
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY);
uint8_t data = SPI_ReceiveData(SPI1);
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE));
if(data==0x82) SPI_SendData(SPI1, 0xCD);
GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}
}
}
/* Private functions ---------------------------------------------------------*/
static void CLK_Config(void)
{
/* Select HSE as system clock source */
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
/*High speed external clock prescaler: 1*/
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
{}
/* Enable SPI clock */
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}
void Delay(__IO uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
/*******************************************************************************/
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* Infinite loop */
while (1)
{
}
}
#endif
PS:
I am on linux and soft tools were not adapted to my OS, so I used some tools to be able to develop with it.
I think it can be useful for some people, so I add it here:
First, the lib were not able to compile with SDCC, so I used the patch I found here:
https://github.com/gicking/STM8-SPL_SDCC_patch
To upload to the uC, I use stm8flash with a ST-LINK V2:
https://github.com/vdudouyt/stm8flash
I also had some trouble to find the lib for the STM8L. Here it is:
https://www.st.com/en/embedded-software/stsw-stm8016.html
PS2:
I understand that it is not easy to answer to hardware related questions. Does anybody knows some websites which are more specified on this kind of questions?
First I'd like to say I'm very new to c++, that's why I'm using the Arduino core and libraries on ESP32, and I would like to apologize for the dumpster fire you're about to see below.
Simply making a custom keyboard with buttons and encoders. When booted, select one of two modes: blekeyboard or ble midi control surface.
The button works in both modes but the encoder only works in whichever mode is declared last. (so in this script order, both the encoder and button in mode 1 blekeyboard works, while only the button works in mode 2.)
What did I do wrong and what can I do? Any suggestions regarding the problem or the overall script is welcome.
Thank you in advance.
#include <Arduino.h>
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
#define ESP32
#include <encoder.h>
#include <Control_Surface.h>
#include <MIDI_Interfaces/BluetoothMIDI_Interface.hpp>
BluetoothMIDI_Interface midi;
const int usermodebutton1 = 2;
const int usermodebutton2 = 0;
int usermode = 0;
// ---------------------- mode 2 MIDI Input Elements ------------------------ //
using namespace MIDI_Notes;
NoteButton csButton1 = {
2,
note(C, 4),
};
CCRotaryEncoder csEnc1 = {
{26, 25}, // pins
MCU::V_POT_1, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
};
// -------------------------- mode 1 blekeyboard --------------------------- //
int kbutton1 = 2;
int kbutton1State;
int keyInterval = 400000;
Encoder kencoder1(25, 26);
int encInterval = 5000;
TickType_t currentTime;
TickType_t previousTime;
long enc1_oldPos = -999;
// ============================================================================= //
void setup()
{
pinMode(usermodebutton1, INPUT_PULLUP);
pinMode(usermodebutton2, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("");
Serial.println("select mode:");
// ----------------------------------------------------------------------------- //
while (true)
{
if (digitalRead(usermodebutton1) == LOW)
{
usermode = 1;
Serial.println("mode 1 selected");
break;
}
if (digitalRead(usermodebutton2) == LOW)
{
usermode = 2;
Serial.println("mode 2 selected");
break;
}
delay(1000);
}
// ----------------------------------------------------------------------------- //
if (usermode == 1)
{
Serial.println("setup mode 1");
Serial.println("Starting BLE work...");
bleKeyboard.begin();
pinMode(kbutton1, INPUT_PULLUP);
previousTime = 0;
}
if (usermode == 2)
{
Serial.println("setup mode 2");
Serial.println("Control Surface BLE starting...");
RelativeCCSender::setMode(relativeCCmode::TWOS_COMPLEMENT);
Control_Surface.begin(); // Initialize Control Surface
}
}
// ============================================================================= //
void loop()
{
while (usermode == 1)
{
while (bleKeyboard.isConnected())
{
// mode 1 encoders
long enc1_newPos = kencoder1.read();
currentTime = esp_timer_get_time();
if (enc1_newPos < enc1_oldPos && currentTime - previousTime > encInterval)
{
enc1_oldPos = enc1_newPos;
previousTime = currentTime;
// bleKeyboard.write(KEY_MEDIA_VOLUME_DOWN);
Serial.print("enc1: ");
Serial.println(enc1_newPos);
}
if (enc1_newPos > enc1_oldPos && currentTime - previousTime > encInterval)
{
enc1_oldPos = enc1_newPos;
previousTime = currentTime;
// bleKeyboard.write(KEY_MEDIA_VOLUME_UP);
Serial.print("enc1: ");
Serial.println(enc1_newPos);
}
// mode 1 keys
kbutton1State = digitalRead(kbutton1);
if (kbutton1State == LOW && currentTime - previousTime > keyInterval)
{
previousTime = currentTime;
Serial.println("button 1 pressed");
bleKeyboard.print("1");
}
}
}
while (usermode == 2)
{
Control_Surface.loop(); // Refresh all elements
}
}
First of all, your code needs general tidying up. Do not instantiate an object after the #include or #define section.
Avoid doing this:
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
#include <MIDI_Interfaces/BluetoothMIDI_Interface.hpp>
BluetoothMIDI_Interface midi;
I generally organise my code as:
// Include libraries
#include <lib1.h>
#include <lib2.h>
...
// Macros
#define SOMETHING_FUNNY value // see the Macro name in capitals?
#define SOMETHING_USEFUL anothervalue
...
/*
* Variables Section.
* Also, I usually categorize my variables section by type: floats, integers, chars, etc. If I ever use booleans I pack them in a section called 'flags'. Also, if a boolean is used inside an interrupt it should be volatile
*/
Type var_name1 = initial_value; // the initaliztion is optional
AnotherType var_name2;
...
// Object instantiation
ClassName object1;
AnotherClassName object2 = new AnotherClassName(constructor_parameters);
...
//Setup Function
void setup(){
// Serial Port initialization goes first
Serial.begin(baudrate);
// Initialization routines --> use functions!
}
void loop(){
// Check for states of your FSM and call the respective function
}
// Functions definitions
output type myFunction1(args){
// Routine
}
...
Second, your code shouts to me 'Finite-States Machines', which is basically what you are implementing but not in a conventional way. Please read Nick Gammon's amazing tutorial on FSMs. This way, you will enumerate your states and trigger actions or events depending on the user's selection or hardware inputs without blocking the flow of the code.
Now, I assume that you have read both the .cpp files from your two libraries and checked if there are no conflicts between them? Also, which encoder.h library are you using? It looks like Paul Stoffregen's library, is it? I ask because his library is heavily based on interrupts and it was coded with some ASM blocks that might be not optimized for the ESP32, but please don't quote me on that. As enhzflep said:
I'd suspect there to be a problem with clashing interrupts.
and I could not agree more on that. If you are using that library, there is a Macro that could save your life:
#define ENCODER_DO_NOT_USE_INTERRUPTS
used in this example from the library's repo
I need to get information about internet package and I was trying with the following code but I don't have experience with C++.
I executed this code from this tutorial http://yuba.stanford.edu/~casado/pcap/section1.html
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h> /* GIMME a libpcap plz! */
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
char *dev; /* name of the device to use */
char *net; /* dot notation of the network address */
char *mask;/* dot notation of the network mask */
int ret; /* return code */
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 netp; /* ip */
bpf_u_int32 maskp;/* subnet mask */
struct in_addr addr;
/* ask pcap to find a valid device for use to sniff on */
dev = pcap_lookupdev(errbuf);
/* error checking */
if(dev == NULL)
{
printf("%s\n",errbuf);
exit(1);
}
/* print out device name */
printf("DEV: %s\n",dev);
/* ask pcap for the network address and mask of the device */
ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);
if(ret == -1)
{
printf("%s\n",errbuf);
exit(1);
}
/* get the network address in a human readable form */
addr.s_addr = netp;
net = inet_ntoa(addr);
if(net == NULL)/* thanks Scott :-P */
{
perror("inet_ntoa");
exit(1);
}
printf("NET: %s\n",net);
/* do the same as above for the device's mask */
addr.s_addr = maskp;
mask = inet_ntoa(addr);
if(mask == NULL)
{
perror("inet_ntoa");
exit(1);
}
printf("MASK: %s\n",mask);
return 0;
}
When I execute this code, I get a file a.out but I cannot open the file, why? How can i pass my information to .csv?
I don't have experience with C++
Although the code may compile using a C++ compiler it looks more like C code. The name of the file, ldev.c, and the compiler used also says that it's a C program.
When I execute this code, I get a file a.out but I cannot open the file, why?
The last step in the tutorial tells you how to compile the program, not how to execute it:
gcc ldev.c -lpcap
That step produces a.out which is the program you are supposed to execute.
To actually execute the program, run the command:
./a.out
Then, if everything works, the output should be something similar to:
DEV: eth0
NET: 192.168.12.0
MASK: 255.255.255.0
Writing to a .csv file is not very different from the basic writing to any other file.
We need to open the file using the library
#include <fstream>
Then we create our file to write to
std::ofstream outputFile;
we open it using
outputFile.open("random.csv");
and start writing using commas as separators
outputFile << "a,b,c,\n";
outputFile << mask << "\n"; // in your case
Then don't forget to close it!
outputFile.close();
I am new using microcontrollers and I am testing the operation of the example code of the platformio id to create a file in an sd, but when I compile it after passing it to ESP32, it throws me the error that appears in the image "Make sure SD card lines have pull-up resistors in place esp32". Is it a code problem or do I need to add some resistance to the connection?
I leave an image of how it is connected
Thanks
/* SD card and FAT filesystem example.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "sdmmc_cmd.h"
static const char *TAG = "example";
// This example can use SDMMC and SPI peripherals to communicate with SD card.
// By default, SDMMC peripheral is used.
// To enable SPI mode, uncomment the following line:
// #define USE_SPI_MODE
// When testing SD and SPI modes, keep in mind that once the card has been
// initialized in SPI mode, it can not be reinitialized in SD mode without
// toggling power to the card.
#ifdef USE_SPI_MODE
// Pin mapping when using SPI mode.
// With this mapping, SD card can be used both in SPI and 1-line SD mode.
// Note that a pull-up on CS line is required in SD mode.
#define PIN_NUM_MISO 2
#define PIN_NUM_MOSI 15
#define PIN_NUM_CLK 14
#define PIN_NUM_CS 13
#endif //USE_SPI_MODE
void app_main(void)
{
ESP_LOGI(TAG, "Initializing SD card");
#ifndef USE_SPI_MODE
ESP_LOGI(TAG, "Using SDMMC peripheral");
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
// To use 1-line SD mode, uncomment the following line:
// host.flags = SDMMC_HOST_FLAG_1BIT;
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
// GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
// Internal pull-ups are not sufficient. However, enabling internal pull-ups
// does make a difference some boards, so we do that here.
gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only
gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only
gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
#else
ESP_LOGI(TAG, "Using SPI peripheral");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = PIN_NUM_MISO;
slot_config.gpio_mosi = PIN_NUM_MOSI;
slot_config.gpio_sck = PIN_NUM_CLK;
slot_config.gpio_cs = PIN_NUM_CS;
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
#endif //USE_SPI_MODE
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5
};
// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
// Please check its source code and implement error recovery when developing
// production applications.
sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set format_if_mount_failed = true.");
} else {
ESP_LOGE(TAG, "Failed to initialize the card (%d). "
"Make sure SD card lines have pull-up resistors in place.", ret);
}
return;
}
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
// Use POSIX and C standard library functions to work with files.
// First create a file.
ESP_LOGI(TAG, "Opening file");
FILE* f = fopen("/sdcard/hello.txt", "w");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "Hello %s!\n", card->cid.name);
fclose(f);
ESP_LOGI(TAG, "File written");
// Check if destination file exists before renaming
struct stat st;
if (stat("/sdcard/foo.txt", &st) == 0) {
// Delete it if it exists
unlink("/sdcard/foo.txt");
}
// Rename original file
ESP_LOGI(TAG, "Renaming file");
if (rename("/sdcard/hello.txt", "/sdcard/foo.txt") != 0) {
ESP_LOGE(TAG, "Rename failed");
return;
}
// Open renamed file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/sdcard/foo.txt", "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[64];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char* pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
// All done, unmount partition and disable SDMMC or SPI peripheral
esp_vfs_fat_sdmmc_unmount();
ESP_LOGI(TAG, "Card unmounted");
}
enter image description here
enter image description here
"Make sure SD card lines have pull-up resistors in place." is the default error message when communication with the SD Card (module) does not work.
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set format_if_mount_failed = true.");
} else {
ESP_LOGE(TAG, "Failed to initialize the card (%d). "
"Make sure SD card lines have pull-up resistors in place.", ret);
}
return;
}
The information about the pull-up resistors is only a hint what might be wrong similar to: Maybe one of your wires is not connected correctly.
I had the same error when I tried that code using an SD-Card module with SPI connection which I used previously with Arduino.
After trying lots of things and looking at info all over the internet it seems to me that this never worked with SPI and an SD-Card module which uses SPI. I remember I found info like "this will be implemented later" but I don't remember where I read that.
Later I found there are other SD-Card modules which don't use SPI.
I used this one and it worked.
https://www.ebay.com/itm/9-Pin-Micro-SD-TF-Card-Reader-Read-Write-Module-Storage-Board-Memory-Arduino/401316600781
This is not connected with SPI and that option has to be selected in the code here:
// This example can use SDMMC and SPI peripherals to communicate with SD card.
// By default, SDMMC peripheral is used.
// To enable SPI mode, uncomment the following line:
//#define USE_SPI_MODE
And later in the code there is this section:
// To use 1-line SD mode, uncomment the following line:
host.flags = SDMMC_HOST_FLAG_1BIT;
I was able to get it running by using the 1BIT mode with above module.
I didn't get it running using all connections (I think that is called SD Mode or 1 Line SD Mode).
Using the test code below, I'm trying to send data over the USART of an xmega128a3u using the simulator in Atmel Studio. Watching the I/O view the Data register is never set even though I'm setting it. Is there something wrong with my code or the simulator or what?
#include <avr/io.h>
#include <avr/interrupt.h>
#define bscale 0
#define bsel 0x0003 //250kbps
#define packetFormat (USART_SBMODE_bm | USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc)
uint8_t n;
int main(void)
{
//ALLOW PORTB AND PORTF TO BE WRITTEN TO! TURNS OFF JTAG
CCP = 0xD8; //Allow Protected IO changing
MCU_MCUCR = 0x1;
//CRYSTAL SETUP
OSC_XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc; // 16Mhz Crystal
OSC_CTRL |= OSC_XOSCEN_bm;
while(!(OSC_STATUS & OSC_XOSCRDY_bm)); //Wait for crystal to stabilize.
CCP = CCP_IOREG_gc;
CLK_CTRL = CLK_SCLKSEL_XOSC_gc;
//END CRYSTAL SETUP
cli();
//Enable Interrupts
USARTF0.CTRLA = USART_TXCINTLVL_LO_gc | USART_DREINTLVL_LO_gc;
//Enable transmitter
USARTF0.CTRLB = USART_TXEN_bm;
PMIC.CTRL |= PMIC_LOLVLEX_bm;
//Set baud
USARTF0.BAUDCTRLB = bscale;
USARTF0.BAUDCTRLA = bsel;
//Set packet format
USARTF0.CTRLC = packetFormat;
sei();
while (1)
{
if(n < 255) {
USARTF0.DATA = n;
} else {
n = 0;
}
}
}
ISR(USARTF0_TXC_vect) {
n++;
}
ISR(USARTF0_DRE_vect) {
n++;
}
Are other registers being updated, just not DATA? If not, make sure you've enabled the clock to the USART. Many micros also use one DATA register for reads and writes. Thus attempting to read the DATA register after writing (I.e., the debug view is doing a read) won't return anything unless data has been received. Thus you'd likely see the same behavior even if executing on hardware.
That said, in my experience the simulator in Atmel Studio isn't very good at simulating interrupts or peripheral operation.
Edit to include informatino from comments below:
Since you can't read back something you just wrote to the DATA register, checking the DREIF flag in the STATUS register right after you write the data will confirm whether or not the data is being transmitted.